{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Question 1: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# import packages for question 1 and 2\n",
    "from bs4 import BeautifulSoup\n",
    "import requests\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "#load wiki data into df_ca\n",
    "url = requests.get('https://en.wikipedia.org/wiki/List_of_postal_codes_of_Canada:_M').text\n",
    "df_ca = BeautifulSoup(url, 'lxml')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "# create an empty dataframe\n",
    "column_names = ['Postalcode','Borough','Neighborhood']\n",
    "toronto = pd.DataFrame(columns = column_names)\n",
    "\n",
    "# loop through table to find elements\n",
    "# tutorial:https://srome.github.io/Parsing-HTML-Tables-in-Python-with-BeautifulSoup-and-pandas/\n",
    "content = df_ca.find('div', class_='mw-parser-output')\n",
    "table = content.table.tbody\n",
    "postcode = 0\n",
    "borough = 0\n",
    "neighborhood = 0\n",
    "\n",
    "\n",
    "for tr in table.find_all('tr'):\n",
    "    i = 0\n",
    "    for td in tr.find_all('td'):\n",
    "        if i == 0:\n",
    "            postcode = td.text\n",
    "            i = i + 1\n",
    "        elif i == 1:\n",
    "            borough = td.text\n",
    "            i = i + 1\n",
    "        elif i == 2: \n",
    "            neighborhood = td.text.strip('\\n').replace(']','')\n",
    "    toronto = toronto.append({'Postalcode': postcode,'Borough': borough,'Neighborhood': neighborhood},ignore_index=True)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Postalcode</th>\n",
       "      <th>Borough</th>\n",
       "      <th>Neighborhood</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>M1B</td>\n",
       "      <td>Scarborough</td>\n",
       "      <td>Rouge, Malvern</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>M1C</td>\n",
       "      <td>Scarborough</td>\n",
       "      <td>Highland Creek, Rouge Hill, Port Union</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>M1E</td>\n",
       "      <td>Scarborough</td>\n",
       "      <td>Guildwood, Morningside, West Hill</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>M1G</td>\n",
       "      <td>Scarborough</td>\n",
       "      <td>Woburn</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>M1H</td>\n",
       "      <td>Scarborough</td>\n",
       "      <td>Cedarbrae</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  Postalcode      Borough                            Neighborhood\n",
       "0        M1B  Scarborough                          Rouge, Malvern\n",
       "1        M1C  Scarborough  Highland Creek, Rouge Hill, Port Union\n",
       "2        M1E  Scarborough       Guildwood, Morningside, West Hill\n",
       "3        M1G  Scarborough                                  Woburn\n",
       "4        M1H  Scarborough                               Cedarbrae"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#data cleaning\n",
    "toronto = toronto[toronto.Borough!='Not assigned']\n",
    "toronto = toronto[toronto.Borough!= 0]\n",
    "toronto.reset_index(drop = True, inplace = True)\n",
    "i = 0\n",
    "for i in range(0,toronto.shape[0]):\n",
    "    if toronto.iloc[i][2] == 'Not assigned':\n",
    "        toronto.iloc[i][2] = toronto.iloc[i][1]\n",
    "        i = i+1\n",
    "                                 \n",
    "df = toronto.groupby(['Postalcode','Borough'])['Neighborhood'].apply(', '.join).reset_index()\n",
    "df = df.dropna()\n",
    "empty = 'Not assigned'\n",
    "df = df[(df.Postalcode != empty ) & (df.Borough != empty) & (df.Neighborhood != empty)]\n",
    "def neighborhood_list(grouped):    \n",
    "    return ', '.join(sorted(grouped['Neighborhood'].tolist()))\n",
    "                    \n",
    "grp = df.groupby(['Postalcode', 'Borough'])\n",
    "df2 = grp.apply(neighborhood_list).reset_index(name='Neighborhood')\n",
    "df2.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(103, 3)\n"
     ]
    }
   ],
   "source": [
    "print(df2.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Question 2:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Postal Code</th>\n",
       "      <th>Latitude</th>\n",
       "      <th>Longitude</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>M1B</td>\n",
       "      <td>43.806686</td>\n",
       "      <td>-79.194353</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>M1C</td>\n",
       "      <td>43.784535</td>\n",
       "      <td>-79.160497</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>M1E</td>\n",
       "      <td>43.763573</td>\n",
       "      <td>-79.188711</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>M1G</td>\n",
       "      <td>43.770992</td>\n",
       "      <td>-79.216917</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>M1H</td>\n",
       "      <td>43.773136</td>\n",
       "      <td>-79.239476</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>M1J</td>\n",
       "      <td>43.744734</td>\n",
       "      <td>-79.239476</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>M1K</td>\n",
       "      <td>43.727929</td>\n",
       "      <td>-79.262029</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>M1L</td>\n",
       "      <td>43.711112</td>\n",
       "      <td>-79.284577</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>M1M</td>\n",
       "      <td>43.716316</td>\n",
       "      <td>-79.239476</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>M1N</td>\n",
       "      <td>43.692657</td>\n",
       "      <td>-79.264848</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>M1P</td>\n",
       "      <td>43.757410</td>\n",
       "      <td>-79.273304</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>M1R</td>\n",
       "      <td>43.750072</td>\n",
       "      <td>-79.295849</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>M1S</td>\n",
       "      <td>43.794200</td>\n",
       "      <td>-79.262029</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>M1T</td>\n",
       "      <td>43.781638</td>\n",
       "      <td>-79.304302</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>M1V</td>\n",
       "      <td>43.815252</td>\n",
       "      <td>-79.284577</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>M1W</td>\n",
       "      <td>43.799525</td>\n",
       "      <td>-79.318389</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>M1X</td>\n",
       "      <td>43.836125</td>\n",
       "      <td>-79.205636</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>M2H</td>\n",
       "      <td>43.803762</td>\n",
       "      <td>-79.363452</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>M2J</td>\n",
       "      <td>43.778517</td>\n",
       "      <td>-79.346556</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>M2K</td>\n",
       "      <td>43.786947</td>\n",
       "      <td>-79.385975</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20</th>\n",
       "      <td>M2L</td>\n",
       "      <td>43.757490</td>\n",
       "      <td>-79.374714</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>21</th>\n",
       "      <td>M2M</td>\n",
       "      <td>43.789053</td>\n",
       "      <td>-79.408493</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>22</th>\n",
       "      <td>M2N</td>\n",
       "      <td>43.770120</td>\n",
       "      <td>-79.408493</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>23</th>\n",
       "      <td>M2P</td>\n",
       "      <td>43.752758</td>\n",
       "      <td>-79.400049</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>24</th>\n",
       "      <td>M2R</td>\n",
       "      <td>43.782736</td>\n",
       "      <td>-79.442259</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25</th>\n",
       "      <td>M3A</td>\n",
       "      <td>43.753259</td>\n",
       "      <td>-79.329656</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>26</th>\n",
       "      <td>M3B</td>\n",
       "      <td>43.745906</td>\n",
       "      <td>-79.352188</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>27</th>\n",
       "      <td>M3C</td>\n",
       "      <td>43.725900</td>\n",
       "      <td>-79.340923</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>28</th>\n",
       "      <td>M3H</td>\n",
       "      <td>43.754328</td>\n",
       "      <td>-79.442259</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>29</th>\n",
       "      <td>M3J</td>\n",
       "      <td>43.767980</td>\n",
       "      <td>-79.487262</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>73</th>\n",
       "      <td>M6C</td>\n",
       "      <td>43.693781</td>\n",
       "      <td>-79.428191</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>74</th>\n",
       "      <td>M6E</td>\n",
       "      <td>43.689026</td>\n",
       "      <td>-79.453512</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75</th>\n",
       "      <td>M6G</td>\n",
       "      <td>43.669542</td>\n",
       "      <td>-79.422564</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>76</th>\n",
       "      <td>M6H</td>\n",
       "      <td>43.669005</td>\n",
       "      <td>-79.442259</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>77</th>\n",
       "      <td>M6J</td>\n",
       "      <td>43.647927</td>\n",
       "      <td>-79.419750</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>78</th>\n",
       "      <td>M6K</td>\n",
       "      <td>43.636847</td>\n",
       "      <td>-79.428191</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>79</th>\n",
       "      <td>M6L</td>\n",
       "      <td>43.713756</td>\n",
       "      <td>-79.490074</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>80</th>\n",
       "      <td>M6M</td>\n",
       "      <td>43.691116</td>\n",
       "      <td>-79.476013</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>81</th>\n",
       "      <td>M6N</td>\n",
       "      <td>43.673185</td>\n",
       "      <td>-79.487262</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>82</th>\n",
       "      <td>M6P</td>\n",
       "      <td>43.661608</td>\n",
       "      <td>-79.464763</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>83</th>\n",
       "      <td>M6R</td>\n",
       "      <td>43.648960</td>\n",
       "      <td>-79.456325</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>84</th>\n",
       "      <td>M6S</td>\n",
       "      <td>43.651571</td>\n",
       "      <td>-79.484450</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>85</th>\n",
       "      <td>M7A</td>\n",
       "      <td>43.662301</td>\n",
       "      <td>-79.389494</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>86</th>\n",
       "      <td>M7R</td>\n",
       "      <td>43.636966</td>\n",
       "      <td>-79.615819</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>87</th>\n",
       "      <td>M7Y</td>\n",
       "      <td>43.662744</td>\n",
       "      <td>-79.321558</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>88</th>\n",
       "      <td>M8V</td>\n",
       "      <td>43.605647</td>\n",
       "      <td>-79.501321</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>89</th>\n",
       "      <td>M8W</td>\n",
       "      <td>43.602414</td>\n",
       "      <td>-79.543484</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>90</th>\n",
       "      <td>M8X</td>\n",
       "      <td>43.653654</td>\n",
       "      <td>-79.506944</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>91</th>\n",
       "      <td>M8Y</td>\n",
       "      <td>43.636258</td>\n",
       "      <td>-79.498509</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>92</th>\n",
       "      <td>M8Z</td>\n",
       "      <td>43.628841</td>\n",
       "      <td>-79.520999</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>93</th>\n",
       "      <td>M9A</td>\n",
       "      <td>43.667856</td>\n",
       "      <td>-79.532242</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>94</th>\n",
       "      <td>M9B</td>\n",
       "      <td>43.650943</td>\n",
       "      <td>-79.554724</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>95</th>\n",
       "      <td>M9C</td>\n",
       "      <td>43.643515</td>\n",
       "      <td>-79.577201</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>96</th>\n",
       "      <td>M9L</td>\n",
       "      <td>43.756303</td>\n",
       "      <td>-79.565963</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>97</th>\n",
       "      <td>M9M</td>\n",
       "      <td>43.724766</td>\n",
       "      <td>-79.532242</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>98</th>\n",
       "      <td>M9N</td>\n",
       "      <td>43.706876</td>\n",
       "      <td>-79.518188</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>99</th>\n",
       "      <td>M9P</td>\n",
       "      <td>43.696319</td>\n",
       "      <td>-79.532242</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>100</th>\n",
       "      <td>M9R</td>\n",
       "      <td>43.688905</td>\n",
       "      <td>-79.554724</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>101</th>\n",
       "      <td>M9V</td>\n",
       "      <td>43.739416</td>\n",
       "      <td>-79.588437</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>102</th>\n",
       "      <td>M9W</td>\n",
       "      <td>43.706748</td>\n",
       "      <td>-79.594054</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>103 rows × 3 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "    Postal Code   Latitude  Longitude\n",
       "0           M1B  43.806686 -79.194353\n",
       "1           M1C  43.784535 -79.160497\n",
       "2           M1E  43.763573 -79.188711\n",
       "3           M1G  43.770992 -79.216917\n",
       "4           M1H  43.773136 -79.239476\n",
       "5           M1J  43.744734 -79.239476\n",
       "6           M1K  43.727929 -79.262029\n",
       "7           M1L  43.711112 -79.284577\n",
       "8           M1M  43.716316 -79.239476\n",
       "9           M1N  43.692657 -79.264848\n",
       "10          M1P  43.757410 -79.273304\n",
       "11          M1R  43.750072 -79.295849\n",
       "12          M1S  43.794200 -79.262029\n",
       "13          M1T  43.781638 -79.304302\n",
       "14          M1V  43.815252 -79.284577\n",
       "15          M1W  43.799525 -79.318389\n",
       "16          M1X  43.836125 -79.205636\n",
       "17          M2H  43.803762 -79.363452\n",
       "18          M2J  43.778517 -79.346556\n",
       "19          M2K  43.786947 -79.385975\n",
       "20          M2L  43.757490 -79.374714\n",
       "21          M2M  43.789053 -79.408493\n",
       "22          M2N  43.770120 -79.408493\n",
       "23          M2P  43.752758 -79.400049\n",
       "24          M2R  43.782736 -79.442259\n",
       "25          M3A  43.753259 -79.329656\n",
       "26          M3B  43.745906 -79.352188\n",
       "27          M3C  43.725900 -79.340923\n",
       "28          M3H  43.754328 -79.442259\n",
       "29          M3J  43.767980 -79.487262\n",
       "..          ...        ...        ...\n",
       "73          M6C  43.693781 -79.428191\n",
       "74          M6E  43.689026 -79.453512\n",
       "75          M6G  43.669542 -79.422564\n",
       "76          M6H  43.669005 -79.442259\n",
       "77          M6J  43.647927 -79.419750\n",
       "78          M6K  43.636847 -79.428191\n",
       "79          M6L  43.713756 -79.490074\n",
       "80          M6M  43.691116 -79.476013\n",
       "81          M6N  43.673185 -79.487262\n",
       "82          M6P  43.661608 -79.464763\n",
       "83          M6R  43.648960 -79.456325\n",
       "84          M6S  43.651571 -79.484450\n",
       "85          M7A  43.662301 -79.389494\n",
       "86          M7R  43.636966 -79.615819\n",
       "87          M7Y  43.662744 -79.321558\n",
       "88          M8V  43.605647 -79.501321\n",
       "89          M8W  43.602414 -79.543484\n",
       "90          M8X  43.653654 -79.506944\n",
       "91          M8Y  43.636258 -79.498509\n",
       "92          M8Z  43.628841 -79.520999\n",
       "93          M9A  43.667856 -79.532242\n",
       "94          M9B  43.650943 -79.554724\n",
       "95          M9C  43.643515 -79.577201\n",
       "96          M9L  43.756303 -79.565963\n",
       "97          M9M  43.724766 -79.532242\n",
       "98          M9N  43.706876 -79.518188\n",
       "99          M9P  43.696319 -79.532242\n",
       "100         M9R  43.688905 -79.554724\n",
       "101         M9V  43.739416 -79.588437\n",
       "102         M9W  43.706748 -79.594054\n",
       "\n",
       "[103 rows x 3 columns]"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dfll= pd.read_csv(\"http://cocl.us/Geospatial_data\")\n",
    "dfll"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Postalcode</th>\n",
       "      <th>Borough</th>\n",
       "      <th>Neighborhood</th>\n",
       "      <th>Latitude</th>\n",
       "      <th>Longitude</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>M1B</td>\n",
       "      <td>Scarborough</td>\n",
       "      <td>Rouge, Malvern</td>\n",
       "      <td>43.806686</td>\n",
       "      <td>-79.194353</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>M1C</td>\n",
       "      <td>Scarborough</td>\n",
       "      <td>Highland Creek, Rouge Hill, Port Union</td>\n",
       "      <td>43.784535</td>\n",
       "      <td>-79.160497</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>M1E</td>\n",
       "      <td>Scarborough</td>\n",
       "      <td>Guildwood, Morningside, West Hill</td>\n",
       "      <td>43.763573</td>\n",
       "      <td>-79.188711</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>M1G</td>\n",
       "      <td>Scarborough</td>\n",
       "      <td>Woburn</td>\n",
       "      <td>43.770992</td>\n",
       "      <td>-79.216917</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>M1H</td>\n",
       "      <td>Scarborough</td>\n",
       "      <td>Cedarbrae</td>\n",
       "      <td>43.773136</td>\n",
       "      <td>-79.239476</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  Postalcode      Borough                            Neighborhood   Latitude  \\\n",
       "0        M1B  Scarborough                          Rouge, Malvern  43.806686   \n",
       "1        M1C  Scarborough  Highland Creek, Rouge Hill, Port Union  43.784535   \n",
       "2        M1E  Scarborough       Guildwood, Morningside, West Hill  43.763573   \n",
       "3        M1G  Scarborough                                  Woburn  43.770992   \n",
       "4        M1H  Scarborough                               Cedarbrae  43.773136   \n",
       "\n",
       "   Longitude  \n",
       "0 -79.194353  \n",
       "1 -79.160497  \n",
       "2 -79.188711  \n",
       "3 -79.216917  \n",
       "4 -79.239476  "
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dfll.rename(columns={'Postal Code':'Postalcode'}, inplace=True)\n",
    "dfll.set_index(\"Postalcode\")\n",
    "df2.set_index(\"Postalcode\")\n",
    "toronto_data=pd.merge(df2, dfll)\n",
    "toronto_data.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Question 3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting package metadata (repodata.json): done\n",
      "Solving environment: - \n",
      "The environment is inconsistent, please check the package plan carefully\n",
      "The following packages are causing the inconsistency:\n",
      "\n",
      "  - defaults/osx-64::numba==0.44.1=py37h6440ff4_0\n",
      "  - defaults/osx-64::_anaconda_depends==2019.03=py37_0\n",
      "  - defaults/osx-64::anaconda==custom=py37_1\n",
      "done\n",
      "\n",
      "\n",
      "==> WARNING: A newer version of conda exists. <==\n",
      "  current version: 4.7.12\n",
      "  latest version: 4.8.0\n",
      "\n",
      "Please update conda by running\n",
      "\n",
      "    $ conda update -n base -c defaults conda\n",
      "\n",
      "\n",
      "\n",
      "## Package Plan ##\n",
      "\n",
      "  environment location: /anaconda3\n",
      "\n",
      "  added / updated specs:\n",
      "    - geopy\n",
      "\n",
      "\n",
      "The following packages will be downloaded:\n",
      "\n",
      "    package                    |            build\n",
      "    ---------------------------|-----------------\n",
      "    ca-certificates-2019.11.28 |       hecc5488_0         145 KB  conda-forge\n",
      "    certifi-2019.11.28         |           py37_0         148 KB  conda-forge\n",
      "    conda-4.8.0                |           py37_1         3.0 MB  conda-forge\n",
      "    geographiclib-1.50         |             py_0          34 KB  conda-forge\n",
      "    geopy-1.20.0               |             py_0          57 KB  conda-forge\n",
      "    openssl-1.1.1d             |       h0b31af3_0         1.9 MB  conda-forge\n",
      "    tbb-2019.8                 |       h770b8ee_0         157 KB  conda-forge\n",
      "    ------------------------------------------------------------\n",
      "                                           Total:         5.4 MB\n",
      "\n",
      "The following NEW packages will be INSTALLED:\n",
      "\n",
      "  geographiclib      conda-forge/noarch::geographiclib-1.50-py_0\n",
      "  geopy              conda-forge/noarch::geopy-1.20.0-py_0\n",
      "  tbb                conda-forge/osx-64::tbb-2019.8-h770b8ee_0\n",
      "\n",
      "The following packages will be UPDATED:\n",
      "\n",
      "  ca-certificates    pkgs/main::ca-certificates-2019.11.27~ --> conda-forge::ca-certificates-2019.11.28-hecc5488_0\n",
      "  conda                      pkgs/main::conda-4.7.12-py37_0 --> conda-forge::conda-4.8.0-py37_1\n",
      "\n",
      "The following packages will be SUPERSEDED by a higher-priority channel:\n",
      "\n",
      "  certifi                                         pkgs/main --> conda-forge\n",
      "  openssl              pkgs/main::openssl-1.1.1d-h1de35cc_3 --> conda-forge::openssl-1.1.1d-h0b31af3_0\n",
      "\n",
      "\n",
      "\n",
      "Downloading and Extracting Packages\n",
      "openssl-1.1.1d       | 1.9 MB    | ##################################### | 100% \n",
      "geographiclib-1.50   | 34 KB     | ##################################### | 100% \n",
      "conda-4.8.0          | 3.0 MB    | ##################################### | 100% \n",
      "certifi-2019.11.28   | 148 KB    | ##################################### | 100% \n",
      "ca-certificates-2019 | 145 KB    | ##################################### | 100% \n",
      "tbb-2019.8           | 157 KB    | ##################################### | 100% \n",
      "geopy-1.20.0         | 57 KB     | ##################################### | 100% \n",
      "Preparing transaction: done\n",
      "Verifying transaction: done\n",
      "Executing transaction: done\n",
      "Collecting package metadata (repodata.json): done\n",
      "Solving environment: done\n",
      "\n",
      "## Package Plan ##\n",
      "\n",
      "  environment location: /anaconda3\n",
      "\n",
      "  added / updated specs:\n",
      "    - folium=0.5.0\n",
      "\n",
      "\n",
      "The following packages will be downloaded:\n",
      "\n",
      "    package                    |            build\n",
      "    ---------------------------|-----------------\n",
      "    altair-4.0.0               |             py_0         606 KB  conda-forge\n",
      "    branca-0.3.1               |             py_0          25 KB  conda-forge\n",
      "    folium-0.5.0               |             py_0          45 KB  conda-forge\n",
      "    vincent-0.4.4              |             py_1          28 KB  conda-forge\n",
      "    ------------------------------------------------------------\n",
      "                                           Total:         704 KB\n",
      "\n",
      "The following NEW packages will be INSTALLED:\n",
      "\n",
      "  altair             conda-forge/noarch::altair-4.0.0-py_0\n",
      "  branca             conda-forge/noarch::branca-0.3.1-py_0\n",
      "  folium             conda-forge/noarch::folium-0.5.0-py_0\n",
      "  vincent            conda-forge/noarch::vincent-0.4.4-py_1\n",
      "\n",
      "\n",
      "\n",
      "Downloading and Extracting Packages\n",
      "altair-4.0.0         | 606 KB    | ##################################### | 100% \n",
      "branca-0.3.1         | 25 KB     | ##################################### | 100% \n",
      "folium-0.5.0         | 45 KB     | ##################################### | 100% \n",
      "vincent-0.4.4        | 28 KB     | ##################################### | 100% \n",
      "Preparing transaction: done\n",
      "Verifying transaction: done\n",
      "Executing transaction: done\n",
      "Libraries imported.\n"
     ]
    }
   ],
   "source": [
    "#import packages\n",
    "import json # library to handle JSON files\n",
    "!conda install -c conda-forge geopy --yes # uncomment this line if you haven't completed the Foursquare API lab\n",
    "from geopy.geocoders import Nominatim # convert an address into latitude and longitude values\n",
    "import requests # library to handle requests\n",
    "from pandas.io.json import json_normalize # tranform JSON file into a pandas dataframe\n",
    "# Matplotlib and associated plotting modules\n",
    "import matplotlib.cm as cm\n",
    "import matplotlib.colors as colors\n",
    "# import k-means from clustering stage\n",
    "from sklearn.cluster import KMeans\n",
    "from sklearn.datasets.samples_generator import make_blobs\n",
    "!conda install -c conda-forge folium=0.5.0 --yes # uncomment this line if you haven't completed the Foursquare API lab\n",
    "import folium # map rendering library\n",
    "from bs4 import BeautifulSoup\n",
    "import lxml\n",
    "print('Libraries imported.')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The geograpical coordinate of Toronto, ON, Canada are 43.653963, -79.387207.\n"
     ]
    }
   ],
   "source": [
    "#Use geopy library to get the latitude and longitude values of Toronto\n",
    "address = 'Toronto, ON, Canada'\n",
    "geolocator = Nominatim(user_agent=\"to_explorer\")\n",
    "location = geolocator.geocode(address)\n",
    "latitude = location.latitude\n",
    "longitude = location.longitude\n",
    "print('The geograpical coordinate of Toronto, ON, Canada are {}, {}.'.format(latitude, longitude))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVMgPSBmYWxzZTsgTF9OT19UT1VDSCA9IGZhbHNlOyBMX0RJU0FCTEVfM0QgPSBmYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2FqYXguZ29vZ2xlYXBpcy5jb20vYWpheC9saWJzL2pxdWVyeS8xLjExLjEvanF1ZXJ5Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdnaXQuY29tL3B5dGhvbi12aXN1YWxpemF0aW9uL2ZvbGl1bS9tYXN0ZXIvZm9saXVtL3RlbXBsYXRlcy9sZWFmbGV0LmF3ZXNvbWUucm90YXRlLmNzcyIvPgogICAgPHN0eWxlPmh0bWwsIGJvZHkge3dpZHRoOiAxMDAlO2hlaWdodDogMTAwJTttYXJnaW46IDA7cGFkZGluZzogMDt9PC9zdHlsZT4KICAgIDxzdHlsZT4jbWFwIHtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtib3R0b206MDtyaWdodDowO2xlZnQ6MDt9PC9zdHlsZT4KICAgIAogICAgICAgICAgICA8c3R5bGU+ICNtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIgewogICAgICAgICAgICAgICAgcG9zaXRpb24gOiByZWxhdGl2ZTsKICAgICAgICAgICAgICAgIHdpZHRoIDogMTAwLjAlOwogICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgICAgICAgICAgdG9wOiAwLjAlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICA8L3N0eWxlPgogICAgICAgIAo8L2hlYWQ+Cjxib2R5PiAgICAKICAgIAogICAgICAgICAgICA8ZGl2IGNsYXNzPSJmb2xpdW0tbWFwIiBpZD0ibWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiIiA+PC9kaXY+CiAgICAgICAgCjwvYm9keT4KPHNjcmlwdD4gICAgCiAgICAKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGJvdW5kcyA9IG51bGw7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgdmFyIG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYiA9IEwubWFwKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ21hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYicsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7Y2VudGVyOiBbNDMuNjUzOTYzLC03OS4zODcyMDddLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgem9vbTogMTAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhCb3VuZHM6IGJvdW5kcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxheWVyczogW10sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JsZENvcHlKdW1wOiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyczogTC5DUlMuRVBTRzM4NTcKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciB0aWxlX2xheWVyXzc4Y2MxNmYzYzdiZDQyYWI5YzAwYjMwMDZlZjdkNmQxID0gTC50aWxlTGF5ZXIoCiAgICAgICAgICAgICAgICAnaHR0cHM6Ly97c30udGlsZS5vcGVuc3RyZWV0bWFwLm9yZy97en0ve3h9L3t5fS5wbmcnLAogICAgICAgICAgICAgICAgewogICJhdHRyaWJ1dGlvbiI6IG51bGwsCiAgImRldGVjdFJldGluYSI6IGZhbHNlLAogICJtYXhab29tIjogMTgsCiAgIm1pblpvb20iOiAxLAogICJub1dyYXAiOiBmYWxzZSwKICAic3ViZG9tYWlucyI6ICJhYmMiCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl82NTI5YTNiYTQyYjc0ZTVkODRhMGM1MDBiZWZhMTRhYiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjgwNjY4NjI5OTk5OTk5NiwtNzkuMTk0MzUzNDAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMTc2ZTcyYTFhMGY1NDZiZDk0MTE1ZDY1ZDJjZTdkMDggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMzMyNWFmNTBkNjhmNDY1YWJjNTkyZjgyYTUzMDQwMWMgPSAkKCc8ZGl2IGlkPSJodG1sXzMzMjVhZjUwZDY4ZjQ2NWFiYzU5MmY4MmE1MzA0MDFjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Sb3VnZSwgTWFsdmVybiwgU2NhcmJvcm91Z2g8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzE3NmU3MmExYTBmNTQ2YmQ5NDExNWQ2NWQyY2U3ZDA4LnNldENvbnRlbnQoaHRtbF8zMzI1YWY1MGQ2OGY0NjVhYmM1OTJmODJhNTMwNDAxYyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82NTI5YTNiYTQyYjc0ZTVkODRhMGM1MDBiZWZhMTRhYi5iaW5kUG9wdXAocG9wdXBfMTc2ZTcyYTFhMGY1NDZiZDk0MTE1ZDY1ZDJjZTdkMDgpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNWRmZjgxOGUxYzcwNDhkNmIyZmQ2YjlkNzE2ZGU4NWEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43ODQ1MzUxLC03OS4xNjA0OTcwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wOGQxNjc3NjE4M2E0ODRmYjI4ZjM0NTlhZTMxNmMzMSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8zZTE3M2FjMTAzNTg0YTA3YmIyNmZkOGI1Yjc0NzJlOSA9ICQoJzxkaXYgaWQ9Imh0bWxfM2UxNzNhYzEwMzU4NGEwN2JiMjZmZDhiNWI3NDcyZTkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhpZ2hsYW5kIENyZWVrLCBSb3VnZSBIaWxsLCBQb3J0IFVuaW9uLCBTY2FyYm9yb3VnaDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMDhkMTY3NzYxODNhNDg0ZmIyOGYzNDU5YWUzMTZjMzEuc2V0Q29udGVudChodG1sXzNlMTczYWMxMDM1ODRhMDdiYjI2ZmQ4YjViNzQ3MmU5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzVkZmY4MThlMWM3MDQ4ZDZiMmZkNmI5ZDcxNmRlODVhLmJpbmRQb3B1cChwb3B1cF8wOGQxNjc3NjE4M2E0ODRmYjI4ZjM0NTlhZTMxNmMzMSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81NDJmODhiZWMyNDA0ZmY4YjNkZWIzY2YxMDFiN2RkMiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc2MzU3MjYsLTc5LjE4ODcxMTVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZjRhMWFhMWM1MGIzNDg0ZDg2ZWY1MmM3ODIyODBlMDAgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYWQyMTc0ODUxMmI4NDRiODg2NzhhYmEyMDYzZmQyNzkgPSAkKCc8ZGl2IGlkPSJodG1sX2FkMjE3NDg1MTJiODQ0Yjg4Njc4YWJhMjA2M2ZkMjc5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5HdWlsZHdvb2QsIE1vcm5pbmdzaWRlLCBXZXN0IEhpbGwsIFNjYXJib3JvdWdoPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mNGExYWExYzUwYjM0ODRkODZlZjUyYzc4MjI4MGUwMC5zZXRDb250ZW50KGh0bWxfYWQyMTc0ODUxMmI4NDRiODg2NzhhYmEyMDYzZmQyNzkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNTQyZjg4YmVjMjQwNGZmOGIzZGViM2NmMTAxYjdkZDIuYmluZFBvcHVwKHBvcHVwX2Y0YTFhYTFjNTBiMzQ4NGQ4NmVmNTJjNzgyMjgwZTAwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2I5NzBiZDVlMTQ3YzRmZmI5YmVhZmYyNjE5YjYyMGZiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzcwOTkyMSwtNzkuMjE2OTE3NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMzFhYjRiNjQyYjNiNDZkMThhMjZlYzgyY2QxM2NlZjUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZTFhZGQ5NzI5ZGRlNDg1NmI5ZTExYzExMDg0N2MyNGUgPSAkKCc8ZGl2IGlkPSJodG1sX2UxYWRkOTcyOWRkZTQ4NTZiOWUxMWMxMTA4NDdjMjRlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Xb2J1cm4sIFNjYXJib3JvdWdoPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zMWFiNGI2NDJiM2I0NmQxOGEyNmVjODJjZDEzY2VmNS5zZXRDb250ZW50KGh0bWxfZTFhZGQ5NzI5ZGRlNDg1NmI5ZTExYzExMDg0N2MyNGUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYjk3MGJkNWUxNDdjNGZmYjliZWFmZjI2MTliNjIwZmIuYmluZFBvcHVwKHBvcHVwXzMxYWI0YjY0MmIzYjQ2ZDE4YTI2ZWM4MmNkMTNjZWY1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2M4NTJkOTNjNmUxNjQ2YzNhMzZkYWE1NjYzY2M3YWY0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzczMTM2LC03OS4yMzk0NzYwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wOWRlM2FkYTUxOGM0YjZiOGQ3MjBjZThmYjU0NzJhOCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83NDlhOGRlMDFiYmI0YjE0Yjg1NWFiZjk5NGEyYWE4MiA9ICQoJzxkaXYgaWQ9Imh0bWxfNzQ5YThkZTAxYmJiNGIxNGI4NTVhYmY5OTRhMmFhODIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNlZGFyYnJhZSwgU2NhcmJvcm91Z2g8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzA5ZGUzYWRhNTE4YzRiNmI4ZDcyMGNlOGZiNTQ3MmE4LnNldENvbnRlbnQoaHRtbF83NDlhOGRlMDFiYmI0YjE0Yjg1NWFiZjk5NGEyYWE4Mik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jODUyZDkzYzZlMTY0NmMzYTM2ZGFhNTY2M2NjN2FmNC5iaW5kUG9wdXAocG9wdXBfMDlkZTNhZGE1MThjNGI2YjhkNzIwY2U4ZmI1NDcyYTgpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMTY0NDE5NGY5ODc3NDM2ZGFlZTJiZjRlOTQ3ODdjNGYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NDQ3MzQyLC03OS4yMzk0NzYwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iN2UyNTA0N2NmMmE0NWEyOGI3NDgwZTFmOWVlZjM1MCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mNjhkODRiNGY0MDk0ZWRlOWE3YWQ5NGFlZGMyMWJmYSA9ICQoJzxkaXYgaWQ9Imh0bWxfZjY4ZDg0YjRmNDA5NGVkZTlhN2FkOTRhZWRjMjFiZmEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlNjYXJib3JvdWdoIFZpbGxhZ2UsIFNjYXJib3JvdWdoPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iN2UyNTA0N2NmMmE0NWEyOGI3NDgwZTFmOWVlZjM1MC5zZXRDb250ZW50KGh0bWxfZjY4ZDg0YjRmNDA5NGVkZTlhN2FkOTRhZWRjMjFiZmEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMTY0NDE5NGY5ODc3NDM2ZGFlZTJiZjRlOTQ3ODdjNGYuYmluZFBvcHVwKHBvcHVwX2I3ZTI1MDQ3Y2YyYTQ1YTI4Yjc0ODBlMWY5ZWVmMzUwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzFmOTQxYTJjYTAyZjQ1ZGViMWFmZjg5NmJiMDdkZjhmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzI3OTI5MiwtNzkuMjYyMDI5NDAwMDAwMDJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNDczZGE0YmY5MzNjNGIxMzg4ZTc1NjNmZDViMmExZDcgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNmZkZTVjMjZkMWFmNDBkODk5Mjg5MDk0NTgzYWQ3YzcgPSAkKCc8ZGl2IGlkPSJodG1sXzZmZGU1YzI2ZDFhZjQwZDg5OTI4OTA5NDU4M2FkN2M3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FYXN0IEJpcmNobW91bnQgUGFyaywgSW9udmlldywgS2VubmVkeSBQYXJrLCBTY2FyYm9yb3VnaDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNDczZGE0YmY5MzNjNGIxMzg4ZTc1NjNmZDViMmExZDcuc2V0Q29udGVudChodG1sXzZmZGU1YzI2ZDFhZjQwZDg5OTI4OTA5NDU4M2FkN2M3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzFmOTQxYTJjYTAyZjQ1ZGViMWFmZjg5NmJiMDdkZjhmLmJpbmRQb3B1cChwb3B1cF80NzNkYTRiZjkzM2M0YjEzODhlNzU2M2ZkNWIyYTFkNyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jNjQ1NDMxZDUwN2Y0ZGY3ODUyZWMzN2Q2ZTIwZjUwYyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcxMTExMTcwMDAwMDAwNCwtNzkuMjg0NTc3Ml0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jNDgyNDZlNGFlYWQ0OGY4YWNhZTQzYTg4NWU4Mjc1NiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81NDk5YWRlOWNkMWM0NWU0OTMwNzM2ODk2MmYyZTdmZiA9ICQoJzxkaXYgaWQ9Imh0bWxfNTQ5OWFkZTljZDFjNDVlNDkzMDczNjg5NjJmMmU3ZmYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNsYWlybGVhLCBHb2xkZW4gTWlsZSwgT2FrcmlkZ2UsIFNjYXJib3JvdWdoPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jNDgyNDZlNGFlYWQ0OGY4YWNhZTQzYTg4NWU4Mjc1Ni5zZXRDb250ZW50KGh0bWxfNTQ5OWFkZTljZDFjNDVlNDkzMDczNjg5NjJmMmU3ZmYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYzY0NTQzMWQ1MDdmNGRmNzg1MmVjMzdkNmUyMGY1MGMuYmluZFBvcHVwKHBvcHVwX2M0ODI0NmU0YWVhZDQ4ZjhhY2FlNDNhODg1ZTgyNzU2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzQxNDRhMmUwNjQzYjQ5YzJhNTk4Y2NiMzRlN2RmMGZjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzE2MzE2LC03OS4yMzk0NzYwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iYmYyNDZmYWM0MDI0MGFkOWM1NjhlY2Y4OWFiZmU4YyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9hMDU1YjU5MTc3NzU0NDc1YmMyNmVhMTk2OTEyMDdlYSA9ICQoJzxkaXYgaWQ9Imh0bWxfYTA1NWI1OTE3Nzc1NDQ3NWJjMjZlYTE5NjkxMjA3ZWEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNsaWZmY3Jlc3QsIENsaWZmc2lkZSwgU2NhcmJvcm91Z2ggVmlsbGFnZSBXZXN0LCBTY2FyYm9yb3VnaDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYmJmMjQ2ZmFjNDAyNDBhZDljNTY4ZWNmODlhYmZlOGMuc2V0Q29udGVudChodG1sX2EwNTViNTkxNzc3NTQ0NzViYzI2ZWExOTY5MTIwN2VhKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzQxNDRhMmUwNjQzYjQ5YzJhNTk4Y2NiMzRlN2RmMGZjLmJpbmRQb3B1cChwb3B1cF9iYmYyNDZmYWM0MDI0MGFkOWM1NjhlY2Y4OWFiZmU4Yyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wYmY5Y2ExMjY4ODE0MDU5OGNmMDQyMjA1MDY3MjUxMyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY5MjY1NzAwMDAwMDAwNCwtNzkuMjY0ODQ4MV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83ZjQ1YjI0ODNkN2Q0ZjliODM3ZDE2ZmEwYTU5YjY1NCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xYzAyNGViZWRiOWQ0ZjBjOTU4N2NhYzk4YjU3OWI3ZSA9ICQoJzxkaXYgaWQ9Imh0bWxfMWMwMjRlYmVkYjlkNGYwYzk1ODdjYWM5OGI1NzliN2UiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJpcmNoIENsaWZmLCBDbGlmZnNpZGUgV2VzdCwgU2NhcmJvcm91Z2g8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzdmNDViMjQ4M2Q3ZDRmOWI4MzdkMTZmYTBhNTliNjU0LnNldENvbnRlbnQoaHRtbF8xYzAyNGViZWRiOWQ0ZjBjOTU4N2NhYzk4YjU3OWI3ZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wYmY5Y2ExMjY4ODE0MDU5OGNmMDQyMjA1MDY3MjUxMy5iaW5kUG9wdXAocG9wdXBfN2Y0NWIyNDgzZDdkNGY5YjgzN2QxNmZhMGE1OWI2NTQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNzdiMTkyMjdmYThmNDNiM2FhMzIxNDg3YTJmOThmMzQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NTc0MDk2LC03OS4yNzMzMDQwMDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9kYzRiMDdmYjU0ZDg0NWYxODM2MDY1M2JjZWRkZTg5NyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83Mzc5Y2FlNzUxNjk0MTE3OWZkMTVjNWJkNTYzMWFmNiA9ICQoJzxkaXYgaWQ9Imh0bWxfNzM3OWNhZTc1MTY5NDExNzlmZDE1YzViZDU2MzFhZjYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRvcnNldCBQYXJrLCBTY2FyYm9yb3VnaCBUb3duIENlbnRyZSwgV2V4Zm9yZCBIZWlnaHRzLCBTY2FyYm9yb3VnaDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZGM0YjA3ZmI1NGQ4NDVmMTgzNjA2NTNiY2VkZGU4OTcuc2V0Q29udGVudChodG1sXzczNzljYWU3NTE2OTQxMTc5ZmQxNWM1YmQ1NjMxYWY2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzc3YjE5MjI3ZmE4ZjQzYjNhYTMyMTQ4N2EyZjk4ZjM0LmJpbmRQb3B1cChwb3B1cF9kYzRiMDdmYjU0ZDg0NWYxODM2MDY1M2JjZWRkZTg5Nyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81M2M2ZmE4YzRhYmQ0YzgwYjNkYzQ3NWRlZWRlYzVhYiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc1MDA3MTUwMDAwMDAwNCwtNzkuMjk1ODQ5MV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83MDdmNWJmODcxOTY0YjkwYTYyZWE1NDE1ODcyNDIyZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8zNjUyNmZlMGJkMWU0MGZkYmY2OGFmZjIzMzg3NzI3ZiA9ICQoJzxkaXYgaWQ9Imh0bWxfMzY1MjZmZTBiZDFlNDBmZGJmNjhhZmYyMzM4NzcyN2YiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk1hcnl2YWxlLCBXZXhmb3JkLCBTY2FyYm9yb3VnaDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNzA3ZjViZjg3MTk2NGI5MGE2MmVhNTQxNTg3MjQyMmUuc2V0Q29udGVudChodG1sXzM2NTI2ZmUwYmQxZTQwZmRiZjY4YWZmMjMzODc3MjdmKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzUzYzZmYThjNGFiZDRjODBiM2RjNDc1ZGVlZGVjNWFiLmJpbmRQb3B1cChwb3B1cF83MDdmNWJmODcxOTY0YjkwYTYyZWE1NDE1ODcyNDIyZSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yMDUwZTc0ZDNkMDA0OGE4OWE0NzU3YmM5NTg3YjM1NyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc5NDIwMDMsLTc5LjI2MjAyOTQwMDAwMDAyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2I0YTdhNTJmMmQzMzQzYzdiMDA2ODgyNmZjZDM4NDU2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzBjMTExZWEwNjQzNDRiNGZiZWQyMjdmNzY3NGVmYjBlID0gJCgnPGRpdiBpZD0iaHRtbF8wYzExMWVhMDY0MzQ0YjRmYmVkMjI3Zjc2NzRlZmIwZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QWdpbmNvdXJ0LCBTY2FyYm9yb3VnaDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYjRhN2E1MmYyZDMzNDNjN2IwMDY4ODI2ZmNkMzg0NTYuc2V0Q29udGVudChodG1sXzBjMTExZWEwNjQzNDRiNGZiZWQyMjdmNzY3NGVmYjBlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzIwNTBlNzRkM2QwMDQ4YTg5YTQ3NTdiYzk1ODdiMzU3LmJpbmRQb3B1cChwb3B1cF9iNGE3YTUyZjJkMzM0M2M3YjAwNjg4MjZmY2QzODQ1Nik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hNTQzZTdlMjdmZmU0Y2MzOTFkYTYyMTJjZjdhNjkwMCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc4MTYzNzUsLTc5LjMwNDMwMjFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZDA5Yzk2OTE4MmY1NDRiMmEwOTc4NjE3ZTUyYzFkMjkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNmYzZjQ1ZmM3MjIyNGJjMzk2YWZiNjYzZmI0MzY3MGIgPSAkKCc8ZGl2IGlkPSJodG1sXzZmM2Y0NWZjNzIyMjRiYzM5NmFmYjY2M2ZiNDM2NzBiIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DbGFya3MgQ29ybmVycywgU3VsbGl2YW4sIFRhbSBPJiMzOTtTaGFudGVyLCBTY2FyYm9yb3VnaDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZDA5Yzk2OTE4MmY1NDRiMmEwOTc4NjE3ZTUyYzFkMjkuc2V0Q29udGVudChodG1sXzZmM2Y0NWZjNzIyMjRiYzM5NmFmYjY2M2ZiNDM2NzBiKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2E1NDNlN2UyN2ZmZTRjYzM5MWRhNjIxMmNmN2E2OTAwLmJpbmRQb3B1cChwb3B1cF9kMDljOTY5MTgyZjU0NGIyYTA5Nzg2MTdlNTJjMWQyOSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83ODE3ODBjNDJmYWQ0ZGQ5YmFlNzRhM2EyMWNmZTBmMyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjgxNTI1MjIsLTc5LjI4NDU3NzJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfODYyODNiZGM3OGE5NGQwMzk4NTc1OGM5N2Y3N2E5YTggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMTkwOGIxMWI2ZjNhNGM0MmFhN2IzOWFiYjVkYTQ0MmUgPSAkKCc8ZGl2IGlkPSJodG1sXzE5MDhiMTFiNmYzYTRjNDJhYTdiMzlhYmI1ZGE0NDJlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5BZ2luY291cnQgTm9ydGgsIEwmIzM5O0Ftb3JlYXV4IEVhc3QsIE1pbGxpa2VuLCBTdGVlbGVzIEVhc3QsIFNjYXJib3JvdWdoPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84NjI4M2JkYzc4YTk0ZDAzOTg1NzU4Yzk3Zjc3YTlhOC5zZXRDb250ZW50KGh0bWxfMTkwOGIxMWI2ZjNhNGM0MmFhN2IzOWFiYjVkYTQ0MmUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNzgxNzgwYzQyZmFkNGRkOWJhZTc0YTNhMjFjZmUwZjMuYmluZFBvcHVwKHBvcHVwXzg2MjgzYmRjNzhhOTRkMDM5ODU3NThjOTdmNzdhOWE4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2VjNDk0M2M2ODJjNjRjMWViZTAwOWQwY2E5ZTY2YWJlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzk5NTI1MjAwMDAwMDA1LC03OS4zMTgzODg3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2FhMjdlM2ZiNjlhYjRkYzViOGZiYWY4NTdhZWFlMmUwID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2JlMjdlOWMxMmNkYzRhN2VhMmUyZmNmYjgwMDQ3YTVjID0gJCgnPGRpdiBpZD0iaHRtbF9iZTI3ZTljMTJjZGM0YTdlYTJlMmZjZmI4MDA0N2E1YyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TCYjMzk7QW1vcmVhdXggV2VzdCwgU2NhcmJvcm91Z2g8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2FhMjdlM2ZiNjlhYjRkYzViOGZiYWY4NTdhZWFlMmUwLnNldENvbnRlbnQoaHRtbF9iZTI3ZTljMTJjZGM0YTdlYTJlMmZjZmI4MDA0N2E1Yyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9lYzQ5NDNjNjgyYzY0YzFlYmUwMDlkMGNhOWU2NmFiZS5iaW5kUG9wdXAocG9wdXBfYWEyN2UzZmI2OWFiNGRjNWI4ZmJhZjg1N2FlYWUyZTApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNzZhNTEwMmJkZjVmNDljYzkzNzhmNTNkMjhkNzg5NWQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My44MzYxMjQ3MDAwMDAwMDYsLTc5LjIwNTYzNjA5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzljODg1ZGUzYzg0ODQ2ZmNiZjQ2YWQ3OGQwNjMyNDJjID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzNiOGVjOTJiZjE4NzRhZDk4OWRlY2EyYzIwYWNmYzUwID0gJCgnPGRpdiBpZD0iaHRtbF8zYjhlYzkyYmYxODc0YWQ5ODlkZWNhMmMyMGFjZmM1MCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VXBwZXIgUm91Z2UsIFNjYXJib3JvdWdoPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85Yzg4NWRlM2M4NDg0NmZjYmY0NmFkNzhkMDYzMjQyYy5zZXRDb250ZW50KGh0bWxfM2I4ZWM5MmJmMTg3NGFkOTg5ZGVjYTJjMjBhY2ZjNTApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNzZhNTEwMmJkZjVmNDljYzkzNzhmNTNkMjhkNzg5NWQuYmluZFBvcHVwKHBvcHVwXzljODg1ZGUzYzg0ODQ2ZmNiZjQ2YWQ3OGQwNjMyNDJjKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2JjOTFkODZmZTQ0MDRiNTM4MDEyODg1MWI5NGRkMTJjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuODAzNzYyMiwtNzkuMzYzNDUxN10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mMDc4YzYzNGEzMzY0YWJlYWE3ODcyNWI1NDIwZWYyOSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF84YTAzOTk5ZDYxMTA0MTQzYmVkNWUwMDZmNzU1ZTcyNiA9ICQoJzxkaXYgaWQ9Imh0bWxfOGEwMzk5OWQ2MTEwNDE0M2JlZDVlMDA2Zjc1NWU3MjYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhpbGxjcmVzdCBWaWxsYWdlLCBOb3J0aCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mMDc4YzYzNGEzMzY0YWJlYWE3ODcyNWI1NDIwZWYyOS5zZXRDb250ZW50KGh0bWxfOGEwMzk5OWQ2MTEwNDE0M2JlZDVlMDA2Zjc1NWU3MjYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYmM5MWQ4NmZlNDQwNGI1MzgwMTI4ODUxYjk0ZGQxMmMuYmluZFBvcHVwKHBvcHVwX2YwNzhjNjM0YTMzNjRhYmVhYTc4NzI1YjU0MjBlZjI5KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzJhZjJlMDViYjQwNjQ1MWViMDM0YTUwMTRlMDU4OWY3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzc4NTE3NSwtNzkuMzQ2NTU1N10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mMjE3MDE5YzM0OTU0OTVhYWU4YjBiYjFjZjc2MGQ3NiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83MTlmZjcxNmQ5MDc0OGYzOGU4ZGQzYTFhMzYzNGE3MSA9ICQoJzxkaXYgaWQ9Imh0bWxfNzE5ZmY3MTZkOTA3NDhmMzhlOGRkM2ExYTM2MzRhNzEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkZhaXJ2aWV3LCBIZW5yeSBGYXJtLCBPcmlvbGUsIE5vcnRoIFlvcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2YyMTcwMTljMzQ5NTQ5NWFhZThiMGJiMWNmNzYwZDc2LnNldENvbnRlbnQoaHRtbF83MTlmZjcxNmQ5MDc0OGYzOGU4ZGQzYTFhMzYzNGE3MSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8yYWYyZTA1YmI0MDY0NTFlYjAzNGE1MDE0ZTA1ODlmNy5iaW5kUG9wdXAocG9wdXBfZjIxNzAxOWMzNDk1NDk1YWFlOGIwYmIxY2Y3NjBkNzYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOTY1ZDFjYzI1ZWQ4NDJhY2I5Yzc3ODgyMTJjODFlMWMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43ODY5NDczLC03OS4zODU5NzVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYTE3OWQ4ODE2NDYyNDY0NDgzYTZkZTI2NmVlMDcxY2YgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMmMxMzk0ZWFjYjMwNGVhZDliMWIxNTJjNTRjYWQzODMgPSAkKCc8ZGl2IGlkPSJodG1sXzJjMTM5NGVhY2IzMDRlYWQ5YjFiMTUyYzU0Y2FkMzgzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5CYXl2aWV3IFZpbGxhZ2UsIE5vcnRoIFlvcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2ExNzlkODgxNjQ2MjQ2NDQ4M2E2ZGUyNjZlZTA3MWNmLnNldENvbnRlbnQoaHRtbF8yYzEzOTRlYWNiMzA0ZWFkOWIxYjE1MmM1NGNhZDM4Myk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85NjVkMWNjMjVlZDg0MmFjYjljNzc4ODIxMmM4MWUxYy5iaW5kUG9wdXAocG9wdXBfYTE3OWQ4ODE2NDYyNDY0NDgzYTZkZTI2NmVlMDcxY2YpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMmI2NTFiOTljYWRmNGNlMGJjMWI4YmY5NDk2ZjU5YzEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NTc0OTAyLC03OS4zNzQ3MTQwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mNWM5YTE2NWQ0Njg0Njg3OWY0MzUxNzkzZmJlYzMzYyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8wOGQwOTY2NGM0MzY0NDk4OTc0NjFkZWMxNWViMTQ2NyA9ICQoJzxkaXYgaWQ9Imh0bWxfMDhkMDk2NjRjNDM2NDQ5ODk3NDYxZGVjMTVlYjE0NjciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlNpbHZlciBIaWxscywgWW9yayBNaWxscywgTm9ydGggWW9yazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZjVjOWExNjVkNDY4NDY4NzlmNDM1MTc5M2ZiZWMzM2Muc2V0Q29udGVudChodG1sXzA4ZDA5NjY0YzQzNjQ0OTg5NzQ2MWRlYzE1ZWIxNDY3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzJiNjUxYjk5Y2FkZjRjZTBiYzFiOGJmOTQ5NmY1OWMxLmJpbmRQb3B1cChwb3B1cF9mNWM5YTE2NWQ0Njg0Njg3OWY0MzUxNzkzZmJlYzMzYyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mZjBkMzlmMzcyY2E0MGI5YTA1ZmM3MmQwYWQwNzkzYyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc4OTA1MywtNzkuNDA4NDkyNzk5OTk5OTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOTY4OGFhZjkyYzMzNDRhZWI0ODFiMjJkOWRiM2Q5OTcgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNzJiZGJmM2E5OTQyNGZjMzhlZTcwZTBhYTY4NjlhNjAgPSAkKCc8ZGl2IGlkPSJodG1sXzcyYmRiZjNhOTk0MjRmYzM4ZWU3MGUwYWE2ODY5YTYwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5OZXd0b25icm9vaywgV2lsbG93ZGFsZSwgTm9ydGggWW9yazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOTY4OGFhZjkyYzMzNDRhZWI0ODFiMjJkOWRiM2Q5OTcuc2V0Q29udGVudChodG1sXzcyYmRiZjNhOTk0MjRmYzM4ZWU3MGUwYWE2ODY5YTYwKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2ZmMGQzOWYzNzJjYTQwYjlhMDVmYzcyZDBhZDA3OTNjLmJpbmRQb3B1cChwb3B1cF85Njg4YWFmOTJjMzM0NGFlYjQ4MWIyMmQ5ZGIzZDk5Nyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9lYWI1YTk2OWM0YmY0MjRhODA0OTc0YzhhMmNiZDk3YyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc3MDExOTksLTc5LjQwODQ5Mjc5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2JiN2Q5OWIzN2QzMzQ2MzFhOGYzODA4MTIxOGE2ODJiID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2Y5ZjQwZjcxMjdhNTQ0ZWRhOGU0YWRlOGE2NTA5ZTY5ID0gJCgnPGRpdiBpZD0iaHRtbF9mOWY0MGY3MTI3YTU0NGVkYThlNGFkZThhNjUwOWU2OSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V2lsbG93ZGFsZSBTb3V0aCwgTm9ydGggWW9yazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYmI3ZDk5YjM3ZDMzNDYzMWE4ZjM4MDgxMjE4YTY4MmIuc2V0Q29udGVudChodG1sX2Y5ZjQwZjcxMjdhNTQ0ZWRhOGU0YWRlOGE2NTA5ZTY5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2VhYjVhOTY5YzRiZjQyNGE4MDQ5NzRjOGEyY2JkOTdjLmJpbmRQb3B1cChwb3B1cF9iYjdkOTliMzdkMzM0NjMxYThmMzgwODEyMThhNjgyYik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81OGUzNWVmNzAyNDU0MjRjOWFlZjg0M2VkNzAzMDUwYiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc1Mjc1ODI5OTk5OTk5NiwtNzkuNDAwMDQ5M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82MmJkYTFjYzI2OWM0OTI0ODlkZjg4MmJiNzFkNzU4OSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iMmE1OGQxZWI4MTQ0NDU0YmIwMDkxNDI0MmRiMzJjNSA9ICQoJzxkaXYgaWQ9Imh0bWxfYjJhNThkMWViODE0NDQ1NGJiMDA5MTQyNDJkYjMyYzUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPllvcmsgTWlsbHMgV2VzdCwgTm9ydGggWW9yazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNjJiZGExY2MyNjljNDkyNDg5ZGY4ODJiYjcxZDc1ODkuc2V0Q29udGVudChodG1sX2IyYTU4ZDFlYjgxNDQ0NTRiYjAwOTE0MjQyZGIzMmM1KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzU4ZTM1ZWY3MDI0NTQyNGM5YWVmODQzZWQ3MDMwNTBiLmJpbmRQb3B1cChwb3B1cF82MmJkYTFjYzI2OWM0OTI0ODlkZjg4MmJiNzFkNzU4OSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81NDZkM2E2N2Y2NzI0N2I1YmM2ZDVlODcyOWRjNWYwZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc4MjczNjQsLTc5LjQ0MjI1OTNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZjUwNzY1YzI4NmZiNGRmMmI1MWE0NWUxN2Y5MjQzMDYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNjhiZTY2NjI5MGRjNDdhZmI0OWMyYzIxMTcyYTUwMzggPSAkKCc8ZGl2IGlkPSJodG1sXzY4YmU2NjYyOTBkYzQ3YWZiNDljMmMyMTE3MmE1MDM4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5XaWxsb3dkYWxlIFdlc3QsIE5vcnRoIFlvcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2Y1MDc2NWMyODZmYjRkZjJiNTFhNDVlMTdmOTI0MzA2LnNldENvbnRlbnQoaHRtbF82OGJlNjY2MjkwZGM0N2FmYjQ5YzJjMjExNzJhNTAzOCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl81NDZkM2E2N2Y2NzI0N2I1YmM2ZDVlODcyOWRjNWYwZi5iaW5kUG9wdXAocG9wdXBfZjUwNzY1YzI4NmZiNGRmMmI1MWE0NWUxN2Y5MjQzMDYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYWRiZGZmNDhjZDFjNDQ4MmI5MWQxOGU2NGEwMDBkOGQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NTMyNTg2LC03OS4zMjk2NTY1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2I5N2RhY2VjMWY5NzQxMmU4YmIzODg5MzU3NWIwMGU1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzc5ZDA2N2NkM2RlZjQwODA4MjAyYjBlZWI1NjIzZDllID0gJCgnPGRpdiBpZD0iaHRtbF83OWQwNjdjZDNkZWY0MDgwODIwMmIwZWViNTYyM2Q5ZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UGFya3dvb2RzLCBOb3J0aCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iOTdkYWNlYzFmOTc0MTJlOGJiMzg4OTM1NzViMDBlNS5zZXRDb250ZW50KGh0bWxfNzlkMDY3Y2QzZGVmNDA4MDgyMDJiMGVlYjU2MjNkOWUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYWRiZGZmNDhjZDFjNDQ4MmI5MWQxOGU2NGEwMDBkOGQuYmluZFBvcHVwKHBvcHVwX2I5N2RhY2VjMWY5NzQxMmU4YmIzODg5MzU3NWIwMGU1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzQ1M2E1MTNiNDliYzRlZmM4MTQ3MTdhNzFlNjFjYWMwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzQ1OTA1Nzk5OTk5OTk2LC03OS4zNTIxODhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZTg1ODUyZWRhZDNjNDJiOGI0YzcwNmQwMGUxNTIwZGQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMjYyMTczYTM3N2ExNDY1ZDg3YzNhN2I4NzNkNWRmN2IgPSAkKCc8ZGl2IGlkPSJodG1sXzI2MjE3M2EzNzdhMTQ2NWQ4N2MzYTdiODczZDVkZjdiIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Eb24gTWlsbHMgTm9ydGgsIE5vcnRoIFlvcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2U4NTg1MmVkYWQzYzQyYjhiNGM3MDZkMDBlMTUyMGRkLnNldENvbnRlbnQoaHRtbF8yNjIxNzNhMzc3YTE0NjVkODdjM2E3Yjg3M2Q1ZGY3Yik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl80NTNhNTEzYjQ5YmM0ZWZjODE0NzE3YTcxZTYxY2FjMC5iaW5kUG9wdXAocG9wdXBfZTg1ODUyZWRhZDNjNDJiOGI0YzcwNmQwMGUxNTIwZGQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZmJiMjhkZjkwMWE5NGRmODlkNjg3ZjFiMThhZWJkZDUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MjU4OTk3MDAwMDAwMSwtNzkuMzQwOTIzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzk4OGNlYmRlODdmZTQ4ZDRhOTRlMzU2YWYwOTQ4ZDU1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzg1ZGJjNjJlNjMwMjQ5NDY4YTA4ZTgxNzFhN2IxYzFiID0gJCgnPGRpdiBpZD0iaHRtbF84NWRiYzYyZTYzMDI0OTQ2OGEwOGU4MTcxYTdiMWMxYiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RmxlbWluZ2RvbiBQYXJrLCBEb24gTWlsbHMgU291dGgsIE5vcnRoIFlvcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzk4OGNlYmRlODdmZTQ4ZDRhOTRlMzU2YWYwOTQ4ZDU1LnNldENvbnRlbnQoaHRtbF84NWRiYzYyZTYzMDI0OTQ2OGEwOGU4MTcxYTdiMWMxYik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mYmIyOGRmOTAxYTk0ZGY4OWQ2ODdmMWIxOGFlYmRkNS5iaW5kUG9wdXAocG9wdXBfOTg4Y2ViZGU4N2ZlNDhkNGE5NGUzNTZhZjA5NDhkNTUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZjQ1YTY3OGI5MTA2NGM0OWEzYmM4ODJlMTc3MjI5MDUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NTQzMjgzLC03OS40NDIyNTkzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzRkNGY5MGQ1YWNmMDRiZmZiMzg5MjNlMmRlMmRmMTcxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzYxODc0ZjBlODY0ZTQ2MDhiMDMyN2UyZjljMDZiMjJlID0gJCgnPGRpdiBpZD0iaHRtbF82MTg3NGYwZTg2NGU0NjA4YjAzMjdlMmY5YzA2YjIyZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmF0aHVyc3QgTWFub3IsIERvd25zdmlldyBOb3J0aCwgV2lsc29uIEhlaWdodHMsIE5vcnRoIFlvcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzRkNGY5MGQ1YWNmMDRiZmZiMzg5MjNlMmRlMmRmMTcxLnNldENvbnRlbnQoaHRtbF82MTg3NGYwZTg2NGU0NjA4YjAzMjdlMmY5YzA2YjIyZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mNDVhNjc4YjkxMDY0YzQ5YTNiYzg4MmUxNzcyMjkwNS5iaW5kUG9wdXAocG9wdXBfNGQ0ZjkwZDVhY2YwNGJmZmIzODkyM2UyZGUyZGYxNzEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfN2YzZDk4OWVmODJkNDIyMzljNDA0NjI2OGY4ZjEwMTcgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43Njc5ODAzLC03OS40ODcyNjE5MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9kODVjMGMyZjZmODY0ZDc2ODIwZDVkZGI5NTAzMGI4YSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8yOGM3NjNiMzI0ZGU0MTgyYmFkNTA2ZGYxYmI0Mzg0MCA9ICQoJzxkaXYgaWQ9Imh0bWxfMjhjNzYzYjMyNGRlNDE4MmJhZDUwNmRmMWJiNDM4NDAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5vcnRod29vZCBQYXJrLCBZb3JrIFVuaXZlcnNpdHksIE5vcnRoIFlvcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2Q4NWMwYzJmNmY4NjRkNzY4MjBkNWRkYjk1MDMwYjhhLnNldENvbnRlbnQoaHRtbF8yOGM3NjNiMzI0ZGU0MTgyYmFkNTA2ZGYxYmI0Mzg0MCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83ZjNkOTg5ZWY4MmQ0MjIzOWM0MDQ2MjY4ZjhmMTAxNy5iaW5kUG9wdXAocG9wdXBfZDg1YzBjMmY2Zjg2NGQ3NjgyMGQ1ZGRiOTUwMzBiOGEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOWNhNTllMjJjYjE1NDQ1ZmE3NTBhZmIyNjA0MWNkYTUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43Mzc0NzMyMDAwMDAwMDQsLTc5LjQ2NDc2MzI5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzgwZDE4MDc1NjU0ODQ5OThhMjI1M2MzNTFkYjk0MjRhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzU1YmVhZjdlNTFjMDRiNTFiYjA4NjdkMGJlNjZjMjFhID0gJCgnPGRpdiBpZD0iaHRtbF81NWJlYWY3ZTUxYzA0YjUxYmIwODY3ZDBiZTY2YzIxYSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q0ZCIFRvcm9udG8sIERvd25zdmlldyBFYXN0LCBOb3J0aCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84MGQxODA3NTY1NDg0OTk4YTIyNTNjMzUxZGI5NDI0YS5zZXRDb250ZW50KGh0bWxfNTViZWFmN2U1MWMwNGI1MWJiMDg2N2QwYmU2NmMyMWEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOWNhNTllMjJjYjE1NDQ1ZmE3NTBhZmIyNjA0MWNkYTUuYmluZFBvcHVwKHBvcHVwXzgwZDE4MDc1NjU0ODQ5OThhMjI1M2MzNTFkYjk0MjRhKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2RhZGJjYjI2MWNmNjQyNWJiMmMxYzAyZjZlYTNkNmNjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzM5MDE0NiwtNzkuNTA2OTQzNl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9kYjE0ZmI4ZTk1MTI0NDYxOTA0MzBhYjI4Mzc4ZjM1MSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xOGEwZTU5ODYwMzI0N2QxYTkwYTlhNmRiNDljZThmZSA9ICQoJzxkaXYgaWQ9Imh0bWxfMThhMGU1OTg2MDMyNDdkMWE5MGE5YTZkYjQ5Y2U4ZmUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRvd25zdmlldyBXZXN0LCBOb3J0aCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9kYjE0ZmI4ZTk1MTI0NDYxOTA0MzBhYjI4Mzc4ZjM1MS5zZXRDb250ZW50KGh0bWxfMThhMGU1OTg2MDMyNDdkMWE5MGE5YTZkYjQ5Y2U4ZmUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZGFkYmNiMjYxY2Y2NDI1YmIyYzFjMDJmNmVhM2Q2Y2MuYmluZFBvcHVwKHBvcHVwX2RiMTRmYjhlOTUxMjQ0NjE5MDQzMGFiMjgzNzhmMzUxKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzAxMmFmOGE2Y2VhZTRmMDI4NzM3YTM1ZGFiZmMxYTcyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzI4NDk2NCwtNzkuNDk1Njk3NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZmM4Yjg3OTA3YjEyNDBkZWI1NzExMDc5YTVlNDZkMzQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZDk0ZDIxMzhhNjEyNDY5OWE4YzM2NGExOTkzYzkwOTggPSAkKCc8ZGl2IGlkPSJodG1sX2Q5NGQyMTM4YTYxMjQ2OTlhOGMzNjRhMTk5M2M5MDk4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Eb3duc3ZpZXcgQ2VudHJhbCwgTm9ydGggWW9yazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZmM4Yjg3OTA3YjEyNDBkZWI1NzExMDc5YTVlNDZkMzQuc2V0Q29udGVudChodG1sX2Q5NGQyMTM4YTYxMjQ2OTlhOGMzNjRhMTk5M2M5MDk4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzAxMmFmOGE2Y2VhZTRmMDI4NzM3YTM1ZGFiZmMxYTcyLmJpbmRQb3B1cChwb3B1cF9mYzhiODc5MDdiMTI0MGRlYjU3MTEwNzlhNWU0NmQzNCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9lZTIyYTcwYTYyYjQ0YmQ0OWVkNGExOTA1ZDE1OTllYSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc2MTYzMTMsLTc5LjUyMDk5OTQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2Q4M2IxNTQ3MmE1OTQzYzNiYzE5ZmM3MWEzZDUwMzI1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzA4YjExYWE0MzhjMjQ2ZWY4YzQxNTNmMTI0MTcwYTlhID0gJCgnPGRpdiBpZD0iaHRtbF8wOGIxMWFhNDM4YzI0NmVmOGM0MTUzZjEyNDE3MGE5YSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RG93bnN2aWV3IE5vcnRod2VzdCwgTm9ydGggWW9yazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZDgzYjE1NDcyYTU5NDNjM2JjMTlmYzcxYTNkNTAzMjUuc2V0Q29udGVudChodG1sXzA4YjExYWE0MzhjMjQ2ZWY4YzQxNTNmMTI0MTcwYTlhKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2VlMjJhNzBhNjJiNDRiZDQ5ZWQ0YTE5MDVkMTU5OWVhLmJpbmRQb3B1cChwb3B1cF9kODNiMTU0NzJhNTk0M2MzYmMxOWZjNzFhM2Q1MDMyNSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yNTJkZTU5YTZhNjQ0MWQ3YTNlODRlYzY0MmNhYmM3NSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcyNTg4MjI5OTk5OTk5NSwtNzkuMzE1NTcxNTk5OTk5OThdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYjhkOTI2NjIyNTY4NGUxZGIyYjlhODc4NGNmZjE5YzYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNzFiNDg1NDc2MGI5NDMyZGI5YzY4N2U3ODU1NDg1YzUgPSAkKCc8ZGl2IGlkPSJodG1sXzcxYjQ4NTQ3NjBiOTQzMmRiOWM2ODdlNzg1NTQ4NWM1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5WaWN0b3JpYSBWaWxsYWdlLCBOb3J0aCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iOGQ5MjY2MjI1Njg0ZTFkYjJiOWE4Nzg0Y2ZmMTljNi5zZXRDb250ZW50KGh0bWxfNzFiNDg1NDc2MGI5NDMyZGI5YzY4N2U3ODU1NDg1YzUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMjUyZGU1OWE2YTY0NDFkN2EzZTg0ZWM2NDJjYWJjNzUuYmluZFBvcHVwKHBvcHVwX2I4ZDkyNjYyMjU2ODRlMWRiMmI5YTg3ODRjZmYxOWM2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzAzODJkNGFlZThiZjRjMzliYzFmYWJiZDJlZmNhMmE1ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzA2Mzk3MiwtNzkuMzA5OTM3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzJkMmIxMzYwMDJiNTRmZjQ4MmE1Mzg4MjhjZTc0ZmUxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzU4MTE4ZDIwODE3ZjQ2MTM4NjFhZTljOGQwZWY2MDg1ID0gJCgnPGRpdiBpZD0iaHRtbF81ODExOGQyMDgxN2Y0NjEzODYxYWU5YzhkMGVmNjA4NSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V29vZGJpbmUgR2FyZGVucywgUGFya3ZpZXcgSGlsbCwgRWFzdCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yZDJiMTM2MDAyYjU0ZmY0ODJhNTM4ODI4Y2U3NGZlMS5zZXRDb250ZW50KGh0bWxfNTgxMThkMjA4MTdmNDYxMzg2MWFlOWM4ZDBlZjYwODUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMDM4MmQ0YWVlOGJmNGMzOWJjMWZhYmJkMmVmY2EyYTUuYmluZFBvcHVwKHBvcHVwXzJkMmIxMzYwMDJiNTRmZjQ4MmE1Mzg4MjhjZTc0ZmUxKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2MxN2Y2MjllMWZhNDQzNzRhNWRiMGZjYjBmYmQ2NjEzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjk1MzQzOTAwMDAwMDA1LC03OS4zMTgzODg3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzk2OTNkZjNlMjc4ODQyYzBhMTk5YzE0MWMyMWM4ODgzID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2MyYmJlMmI1YmNmYzRmNTQ4OTk3ODE0MGYyMjAzMWM5ID0gJCgnPGRpdiBpZD0iaHRtbF9jMmJiZTJiNWJjZmM0ZjU0ODk5NzgxNDBmMjIwMzFjOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V29vZGJpbmUgSGVpZ2h0cywgRWFzdCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85NjkzZGYzZTI3ODg0MmMwYTE5OWMxNDFjMjFjODg4My5zZXRDb250ZW50KGh0bWxfYzJiYmUyYjViY2ZjNGY1NDg5OTc4MTQwZjIyMDMxYzkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYzE3ZjYyOWUxZmE0NDM3NGE1ZGIwZmNiMGZiZDY2MTMuYmluZFBvcHVwKHBvcHVwXzk2OTNkZjNlMjc4ODQyYzBhMTk5YzE0MWMyMWM4ODgzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzFmNjY5YzhiZWE3ZTRiZjNhZTY0NjFlYmYyMzYxMjNjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjc2MzU3Mzk5OTk5OTksLTc5LjI5MzAzMTJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYzdlZmVmOTFkYzQzNDNmZGFjNjQ1ZDQ0MzdjZjY2ZjUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfN2UwZDY2ZGU1OWRiNDUyYjk1MTIwZjAxMDE1MzNiMTAgPSAkKCc8ZGl2IGlkPSJodG1sXzdlMGQ2NmRlNTlkYjQ1MmI5NTEyMGYwMTAxNTMzYjEwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5UaGUgQmVhY2hlcywgRWFzdCBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jN2VmZWY5MWRjNDM0M2ZkYWM2NDVkNDQzN2NmNjZmNS5zZXRDb250ZW50KGh0bWxfN2UwZDY2ZGU1OWRiNDUyYjk1MTIwZjAxMDE1MzNiMTApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMWY2NjljOGJlYTdlNGJmM2FlNjQ2MWViZjIzNjEyM2MuYmluZFBvcHVwKHBvcHVwX2M3ZWZlZjkxZGM0MzQzZmRhYzY0NWQ0NDM3Y2Y2NmY1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzIwYjcyYmRkOWFlMjQ1YjY4YWZmMGMwOTkwNDQwMzNhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzA5MDYwNCwtNzkuMzYzNDUxN10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yMTI4MWU4M2E3ZjU0NjRhYmU3ZTQ5ZGRiOTVhNDRkNCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9hMGUwZThhYzhhN2M0YTM3OTFhN2QzYjI1ZjBjYmQ5YyA9ICQoJzxkaXYgaWQ9Imh0bWxfYTBlMGU4YWM4YTdjNGEzNzkxYTdkM2IyNWYwY2JkOWMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkxlYXNpZGUsIEVhc3QgWW9yazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMjEyODFlODNhN2Y1NDY0YWJlN2U0OWRkYjk1YTQ0ZDQuc2V0Q29udGVudChodG1sX2EwZTBlOGFjOGE3YzRhMzc5MWE3ZDNiMjVmMGNiZDljKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzIwYjcyYmRkOWFlMjQ1YjY4YWZmMGMwOTkwNDQwMzNhLmJpbmRQb3B1cChwb3B1cF8yMTI4MWU4M2E3ZjU0NjRhYmU3ZTQ5ZGRiOTVhNDRkNCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81YmY5ZDFjN2M4Mzk0MGY3OGE1NmQwYTk4ZTZlOWE0NSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcwNTM2ODksLTc5LjM0OTM3MTkwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2IxMDBiODNmNzc5ZjQ2YjZhMzViZGQxMmVhZTA3NzYxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzNkYmJiYTIzOTExMTQwNDlhMjZlNGQ2NTUzOGFiNTZkID0gJCgnPGRpdiBpZD0iaHRtbF8zZGJiYmEyMzkxMTE0MDQ5YTI2ZTRkNjU1MzhhYjU2ZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VGhvcm5jbGlmZmUgUGFyaywgRWFzdCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iMTAwYjgzZjc3OWY0NmI2YTM1YmRkMTJlYWUwNzc2MS5zZXRDb250ZW50KGh0bWxfM2RiYmJhMjM5MTExNDA0OWEyNmU0ZDY1NTM4YWI1NmQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNWJmOWQxYzdjODM5NDBmNzhhNTZkMGE5OGU2ZTlhNDUuYmluZFBvcHVwKHBvcHVwX2IxMDBiODNmNzc5ZjQ2YjZhMzViZGQxMmVhZTA3NzYxKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Y3NTZhODEyMDNmNzQyZDU4NGUzZDRlNWZjNzY1ZDAxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjg1MzQ3LC03OS4zMzgxMDY1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2Y4ZjI5MjczNmMxOTQwOWM4NmFlYjM2ZDcyMDhkYzU3ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzM2NzMwNGU2M2E1ODQzZTQ4ODY2ZmMzZWM3ZTIyY2JmID0gJCgnPGRpdiBpZD0iaHRtbF8zNjczMDRlNjNhNTg0M2U0ODg2NmZjM2VjN2UyMmNiZiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RWFzdCBUb3JvbnRvLCBFYXN0IFlvcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2Y4ZjI5MjczNmMxOTQwOWM4NmFlYjM2ZDcyMDhkYzU3LnNldENvbnRlbnQoaHRtbF8zNjczMDRlNjNhNTg0M2U0ODg2NmZjM2VjN2UyMmNiZik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mNzU2YTgxMjAzZjc0MmQ1ODRlM2Q0ZTVmYzc2NWQwMS5iaW5kUG9wdXAocG9wdXBfZjhmMjkyNzM2YzE5NDA5Yzg2YWViMzZkNzIwOGRjNTcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOGVmYzMzZTdiYzI1NGQ5NDhmNGViYjU2MWFmNTdiZTEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42Nzk1NTcxLC03OS4zNTIxODhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNjZhYjgzZGJiZWVkNDVlYmFkMmJhZGMyODdiMTA3MWUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOWI5MmZhODgwNzFiNGJjNmIxNTM0MzA1MDI3MWQ4NjAgPSAkKCc8ZGl2IGlkPSJodG1sXzliOTJmYTg4MDcxYjRiYzZiMTUzNDMwNTAyNzFkODYwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5UaGUgRGFuZm9ydGggV2VzdCwgUml2ZXJkYWxlLCBFYXN0IFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzY2YWI4M2RiYmVlZDQ1ZWJhZDJiYWRjMjg3YjEwNzFlLnNldENvbnRlbnQoaHRtbF85YjkyZmE4ODA3MWI0YmM2YjE1MzQzMDUwMjcxZDg2MCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl84ZWZjMzNlN2JjMjU0ZDk0OGY0ZWJiNTYxYWY1N2JlMS5iaW5kUG9wdXAocG9wdXBfNjZhYjgzZGJiZWVkNDVlYmFkMmJhZGMyODdiMTA3MWUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNWFmNjEzNGVkZTMxNDUxYzkyOThiZjY0NzU2MTdkYjEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42Njg5OTg1LC03OS4zMTU1NzE1OTk5OTk5OF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83OTNhOGNlYTVhMDg0YTI2YjdmYjJiMTJkMmU3NmNkMCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF82YzMyZmQ5YTA4ZDY0MDBmYWZlNGViZjVlYzJhOTY5YyA9ICQoJzxkaXYgaWQ9Imh0bWxfNmMzMmZkOWEwOGQ2NDAwZmFmZTRlYmY1ZWMyYTk2OWMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlRoZSBCZWFjaGVzIFdlc3QsIEluZGlhIEJhemFhciwgRWFzdCBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83OTNhOGNlYTVhMDg0YTI2YjdmYjJiMTJkMmU3NmNkMC5zZXRDb250ZW50KGh0bWxfNmMzMmZkOWEwOGQ2NDAwZmFmZTRlYmY1ZWMyYTk2OWMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNWFmNjEzNGVkZTMxNDUxYzkyOThiZjY0NzU2MTdkYjEuYmluZFBvcHVwKHBvcHVwXzc5M2E4Y2VhNWEwODRhMjZiN2ZiMmIxMmQyZTc2Y2QwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzhhMzE4MjU1YzYyNDRjNWE4MDM2YmU2ODg5ZjRkNGYxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjU5NTI1NSwtNzkuMzQwOTIzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2UyY2QxYjEwNGZjZDQxODA4ZmU4MTU3NDljNWUzZGE5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzQxNDgxNDBjYTMwMzQwNWRiOTNkNTY4NWFjNzlhNzAxID0gJCgnPGRpdiBpZD0iaHRtbF80MTQ4MTQwY2EzMDM0MDVkYjkzZDU2ODVhYzc5YTcwMSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U3R1ZGlvIERpc3RyaWN0LCBFYXN0IFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2UyY2QxYjEwNGZjZDQxODA4ZmU4MTU3NDljNWUzZGE5LnNldENvbnRlbnQoaHRtbF80MTQ4MTQwY2EzMDM0MDVkYjkzZDU2ODVhYzc5YTcwMSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl84YTMxODI1NWM2MjQ0YzVhODAzNmJlNjg4OWY0ZDRmMS5iaW5kUG9wdXAocG9wdXBfZTJjZDFiMTA0ZmNkNDE4MDhmZTgxNTc0OWM1ZTNkYTkpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZDIyODcyNjU5NjljNDZiMGFiZGFiYjc2MWUxNjg3ZjggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MjgwMjA1LC03OS4zODg3OTAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2U1Y2U0OGE3YTBlODRiODRhM2UyNDllMmM4ZmNhZWQyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzViM2JiOTU4MGUyYTRiOGU4ZDRjOTc3NzliMmI4ZjVhID0gJCgnPGRpdiBpZD0iaHRtbF81YjNiYjk1ODBlMmE0YjhlOGQ0Yzk3Nzc5YjJiOGY1YSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TGF3cmVuY2UgUGFyaywgQ2VudHJhbCBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9lNWNlNDhhN2EwZTg0Yjg0YTNlMjQ5ZTJjOGZjYWVkMi5zZXRDb250ZW50KGh0bWxfNWIzYmI5NTgwZTJhNGI4ZThkNGM5Nzc3OWIyYjhmNWEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZDIyODcyNjU5NjljNDZiMGFiZGFiYjc2MWUxNjg3ZjguYmluZFBvcHVwKHBvcHVwX2U1Y2U0OGE3YTBlODRiODRhM2UyNDllMmM4ZmNhZWQyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzU1YzM1Nzc5Zjk0NTQ4ZDZiMTZhZmM5NjE5Y2UyMmJiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzEyNzUxMSwtNzkuMzkwMTk3NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iOWRiN2NhZGY1OGI0ZTNjOWNhYzliOWU0YWY1YTZkYyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8yODEzNjRhMGE2MWQ0MDI1OTYxMzVjOTYwMDhkZTQ3NSA9ICQoJzxkaXYgaWQ9Imh0bWxfMjgxMzY0YTBhNjFkNDAyNTk2MTM1Yzk2MDA4ZGU0NzUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRhdmlzdmlsbGUgTm9ydGgsIENlbnRyYWwgVG9yb250bzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYjlkYjdjYWRmNThiNGUzYzljYWM5YjllNGFmNWE2ZGMuc2V0Q29udGVudChodG1sXzI4MTM2NGEwYTYxZDQwMjU5NjEzNWM5NjAwOGRlNDc1KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzU1YzM1Nzc5Zjk0NTQ4ZDZiMTZhZmM5NjE5Y2UyMmJiLmJpbmRQb3B1cChwb3B1cF9iOWRiN2NhZGY1OGI0ZTNjOWNhYzliOWU0YWY1YTZkYyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8zNDBjMzdiZWQ4ZDI0MGE1YTZhNWM0ZGQ1M2FlMGY2ZSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcxNTM4MzQsLTc5LjQwNTY3ODQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2M2MmI3ZGUzOGU0NjQ2OWE5ZTkyNmVmMGRmNGM5ODA5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzc0MGY1NTFjODAxNzRmNTQ4NDVlYTEzZjY3MWQ5ZGI1ID0gJCgnPGRpdiBpZD0iaHRtbF83NDBmNTUxYzgwMTc0ZjU0ODQ1ZWExM2Y2NzFkOWRiNSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Tm9ydGggVG9yb250byBXZXN0LCBDZW50cmFsIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2M2MmI3ZGUzOGU0NjQ2OWE5ZTkyNmVmMGRmNGM5ODA5LnNldENvbnRlbnQoaHRtbF83NDBmNTUxYzgwMTc0ZjU0ODQ1ZWExM2Y2NzFkOWRiNSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8zNDBjMzdiZWQ4ZDI0MGE1YTZhNWM0ZGQ1M2FlMGY2ZS5iaW5kUG9wdXAocG9wdXBfYzYyYjdkZTM4ZTQ2NDY5YTllOTI2ZWYwZGY0Yzk4MDkpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYzQyN2ViOWYyZGY5NGY3M2E0YTYzZDQ5MTkwYmNjYzcgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MDQzMjQ0LC03OS4zODg3OTAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzgyOTg0OTllY2YzZTRlMzI5OTFjN2FkODQwOTdjMGI3ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2I1OGZkYmNjYzZlZTQxODU4MTcyZDlhOWFmZDg1NzllID0gJCgnPGRpdiBpZD0iaHRtbF9iNThmZGJjY2M2ZWU0MTg1ODE3MmQ5YTlhZmQ4NTc5ZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RGF2aXN2aWxsZSwgQ2VudHJhbCBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84Mjk4NDk5ZWNmM2U0ZTMyOTkxYzdhZDg0MDk3YzBiNy5zZXRDb250ZW50KGh0bWxfYjU4ZmRiY2NjNmVlNDE4NTgxNzJkOWE5YWZkODU3OWUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYzQyN2ViOWYyZGY5NGY3M2E0YTYzZDQ5MTkwYmNjYzcuYmluZFBvcHVwKHBvcHVwXzgyOTg0OTllY2YzZTRlMzI5OTFjN2FkODQwOTdjMGI3KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzFjZTljMTM3YTdhNTQ4YjA5OGJiMjVhYjgyMjk1NmViID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjg5NTc0MywtNzkuMzgzMTU5OTAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZDYxMWExNDEyNGI3NGUxOThkMTdiNTc2ZmQ0YzQ4NGMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYTA3OWNjZjZlNjNmNDBhMDhkZjBlYjc5NmIyZmNlZGQgPSAkKCc8ZGl2IGlkPSJodG1sX2EwNzljY2Y2ZTYzZjQwYTA4ZGYwZWI3OTZiMmZjZWRkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Nb29yZSBQYXJrLCBTdW1tZXJoaWxsIEVhc3QsIENlbnRyYWwgVG9yb250bzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZDYxMWExNDEyNGI3NGUxOThkMTdiNTc2ZmQ0YzQ4NGMuc2V0Q29udGVudChodG1sX2EwNzljY2Y2ZTYzZjQwYTA4ZGYwZWI3OTZiMmZjZWRkKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzFjZTljMTM3YTdhNTQ4YjA5OGJiMjVhYjgyMjk1NmViLmJpbmRQb3B1cChwb3B1cF9kNjExYTE0MTI0Yjc0ZTE5OGQxN2I1NzZmZDRjNDg0Yyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kYzQ3ZDI0NGFmMjM0NzViYjNhOTMyMzVlZDNhMzEwZSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY4NjQxMjI5OTk5OTk5LC03OS40MDAwNDkzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2YxMWUzMzFhZGU0MDQ2Y2M5N2NmMTFlZTdkZmEwYjVlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzc5ZDVjZTQ2MmYwODQ0YWM4YTY2N2E2OGEyNDAxYzg4ID0gJCgnPGRpdiBpZD0iaHRtbF83OWQ1Y2U0NjJmMDg0NGFjOGE2NjdhNjhhMjQwMWM4OCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RGVlciBQYXJrLCBGb3Jlc3QgSGlsbCBTRSwgUmF0aG5lbGx5LCBTb3V0aCBIaWxsLCBTdW1tZXJoaWxsIFdlc3QsIENlbnRyYWwgVG9yb250bzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZjExZTMzMWFkZTQwNDZjYzk3Y2YxMWVlN2RmYTBiNWUuc2V0Q29udGVudChodG1sXzc5ZDVjZTQ2MmYwODQ0YWM4YTY2N2E2OGEyNDAxYzg4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2RjNDdkMjQ0YWYyMzQ3NWJiM2E5MzIzNWVkM2EzMTBlLmJpbmRQb3B1cChwb3B1cF9mMTFlMzMxYWRlNDA0NmNjOTdjZjExZWU3ZGZhMGI1ZSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80OGU4OWI0OGZmMDY0MGI1YTMyMTIzNjdlYjIxOTQxMCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY3OTU2MjYsLTc5LjM3NzUyOTQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzY5OWM3ODJiYWZhNDQ4NDNiYjg2OWEzNjg0NmVjOTU1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2I1MjQzZjFlYzYyZjQyZGRiOGVmNTU1NzE2Y2IwNDA5ID0gJCgnPGRpdiBpZD0iaHRtbF9iNTI0M2YxZWM2MmY0MmRkYjhlZjU1NTcxNmNiMDQwOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Um9zZWRhbGUsIERvd250b3duIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzY5OWM3ODJiYWZhNDQ4NDNiYjg2OWEzNjg0NmVjOTU1LnNldENvbnRlbnQoaHRtbF9iNTI0M2YxZWM2MmY0MmRkYjhlZjU1NTcxNmNiMDQwOSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl80OGU4OWI0OGZmMDY0MGI1YTMyMTIzNjdlYjIxOTQxMC5iaW5kUG9wdXAocG9wdXBfNjk5Yzc4MmJhZmE0NDg0M2JiODY5YTM2ODQ2ZWM5NTUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfN2EwMWI5OGVmZjk5NDliNzhkNzcwY2IwNWY3NDRlZTQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42Njc5NjcsLTc5LjM2NzY3NTNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNTBiNDI0MWVmZWY5NDNkN2I2NmIzYTMzN2Q3ZWI3ZTMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNjY0YmU0MzA2Yzc0NDZlMThjMGZhMzcyOWFlMjBhM2MgPSAkKCc8ZGl2IGlkPSJodG1sXzY2NGJlNDMwNmM3NDQ2ZTE4YzBmYTM3MjlhZTIwYTNjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DYWJiYWdldG93biwgU3QuIEphbWVzIFRvd24sIERvd250b3duIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzUwYjQyNDFlZmVmOTQzZDdiNjZiM2EzMzdkN2ViN2UzLnNldENvbnRlbnQoaHRtbF82NjRiZTQzMDZjNzQ0NmUxOGMwZmEzNzI5YWUyMGEzYyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83YTAxYjk4ZWZmOTk0OWI3OGQ3NzBjYjA1Zjc0NGVlNC5iaW5kUG9wdXAocG9wdXBfNTBiNDI0MWVmZWY5NDNkN2I2NmIzYTMzN2Q3ZWI3ZTMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfM2NiMzY1ZmY5NTVlNDkxMGJlYjdkNDAxNDkwNjhhNjYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NjU4NTk5LC03OS4zODMxNTk5MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yOWI5MmUxMjYwMTM0ZDQ4OTA1YjExMGU1YjY5ZjYxMiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xOGE3ZWY1OTIwN2I0ZjEwOThlM2Y0MmYwODE1YzU3NSA9ICQoJzxkaXYgaWQ9Imh0bWxfMThhN2VmNTkyMDdiNGYxMDk4ZTNmNDJmMDgxNWM1NzUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNodXJjaCBhbmQgV2VsbGVzbGV5LCBEb3dudG93biBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yOWI5MmUxMjYwMTM0ZDQ4OTA1YjExMGU1YjY5ZjYxMi5zZXRDb250ZW50KGh0bWxfMThhN2VmNTkyMDdiNGYxMDk4ZTNmNDJmMDgxNWM1NzUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfM2NiMzY1ZmY5NTVlNDkxMGJlYjdkNDAxNDkwNjhhNjYuYmluZFBvcHVwKHBvcHVwXzI5YjkyZTEyNjAxMzRkNDg5MDViMTEwZTViNjlmNjEyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzM1MzExYzk0NmZkYjQ3YTdiZGIyZWQ3MzFmYmVlMzI0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjU0MjU5OSwtNzkuMzYwNjM1OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jMTNmNTA3YjUyOGM0MDU5ODIwZTdhOWM5OTliMGQ5MCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83MTJkMWNhOGY0NWE0Mjc1ODM1NGNkYmJiMzFiMTk4MSA9ICQoJzxkaXYgaWQ9Imh0bWxfNzEyZDFjYThmNDVhNDI3NTgzNTRjZGJiYjMxYjE5ODEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhhcmJvdXJmcm9udCwgRG93bnRvd24gVG9yb250bzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYzEzZjUwN2I1MjhjNDA1OTgyMGU3YTljOTk5YjBkOTAuc2V0Q29udGVudChodG1sXzcxMmQxY2E4ZjQ1YTQyNzU4MzU0Y2RiYmIzMWIxOTgxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzM1MzExYzk0NmZkYjQ3YTdiZGIyZWQ3MzFmYmVlMzI0LmJpbmRQb3B1cChwb3B1cF9jMTNmNTA3YjUyOGM0MDU5ODIwZTdhOWM5OTliMGQ5MCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8zZmZkMGE1M2U0MTk0YjQwYTM5MWE0ZmMwZTM1NTYzNyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY1NzE2MTgsLTc5LjM3ODkzNzA5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzg3ZGUwMDdhMGVjNTRkYjJhYmVmMDA0NDAxMDczMDEzID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzU5MTllMWE5ZTljNDQyY2U4YWY1N2ZjNDk0YzU2ZGE0ID0gJCgnPGRpdiBpZD0iaHRtbF81OTE5ZTFhOWU5YzQ0MmNlOGFmNTdmYzQ5NGM1NmRhNCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UnllcnNvbiwgR2FyZGVuIERpc3RyaWN0LCBEb3dudG93biBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84N2RlMDA3YTBlYzU0ZGIyYWJlZjAwNDQwMTA3MzAxMy5zZXRDb250ZW50KGh0bWxfNTkxOWUxYTllOWM0NDJjZThhZjU3ZmM0OTRjNTZkYTQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfM2ZmZDBhNTNlNDE5NGI0MGEzOTFhNGZjMGUzNTU2MzcuYmluZFBvcHVwKHBvcHVwXzg3ZGUwMDdhMGVjNTRkYjJhYmVmMDA0NDAxMDczMDEzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2U0OTJmYzNmZTk3MDRjMGRhNGJjMGE1ZDdjYjc4YTNhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjUxNDkzOSwtNzkuMzc1NDE3OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9lNTI1NjMwMTVmNmQ0YTY5YjE2ZGZhNjdhMjUxMDllMyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83NTIwODQ2NDRkYzY0ODM5YWUzYTRhNGRkN2I5MmRiNyA9ICQoJzxkaXYgaWQ9Imh0bWxfNzUyMDg0NjQ0ZGM2NDgzOWFlM2E0YTRkZDdiOTJkYjciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlN0LiBKYW1lcyBUb3duLCBEb3dudG93biBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9lNTI1NjMwMTVmNmQ0YTY5YjE2ZGZhNjdhMjUxMDllMy5zZXRDb250ZW50KGh0bWxfNzUyMDg0NjQ0ZGM2NDgzOWFlM2E0YTRkZDdiOTJkYjcpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZTQ5MmZjM2ZlOTcwNGMwZGE0YmMwYTVkN2NiNzhhM2EuYmluZFBvcHVwKHBvcHVwX2U1MjU2MzAxNWY2ZDRhNjliMTZkZmE2N2EyNTEwOWUzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzdmOTMwZmEwOGUyOTQ1MjQ4N2U4ZGZhOTA3ZmFiYmJmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjQ0NzcwNzk5OTk5OTk2LC03OS4zNzMzMDY0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzdiMmI5NzhkZDEwMjQyNjJiYjBkMTMwNTBkMmE0NmUyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzA1ZmJhYmVhNGIwMDQ4ZWI4ZjI2ZTg5OTg4N2UxNTZiID0gJCgnPGRpdiBpZD0iaHRtbF8wNWZiYWJlYTRiMDA0OGViOGYyNmU4OTk4ODdlMTU2YiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmVyY3p5IFBhcmssIERvd250b3duIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzdiMmI5NzhkZDEwMjQyNjJiYjBkMTMwNTBkMmE0NmUyLnNldENvbnRlbnQoaHRtbF8wNWZiYWJlYTRiMDA0OGViOGYyNmU4OTk4ODdlMTU2Yik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83ZjkzMGZhMDhlMjk0NTI0ODdlOGRmYTkwN2ZhYmJiZi5iaW5kUG9wdXAocG9wdXBfN2IyYjk3OGRkMTAyNDI2MmJiMGQxMzA1MGQyYTQ2ZTIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMWViOWUxMDdkYWQ1NGRjNmJlZTE5YmU1MjJkODc3MTYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NTc5NTI0LC03OS4zODczODI2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2Y4NTIxYjVkY2U3NDQwMzNhOTc2MmM3MTMxMjExYjUwID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2IzZWFlODdlMDcwYzQ3MDlhMzgxZTU1MDFjYWQ0ZDQ2ID0gJCgnPGRpdiBpZD0iaHRtbF9iM2VhZTg3ZTA3MGM0NzA5YTM4MWU1NTAxY2FkNGQ0NiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q2VudHJhbCBCYXkgU3RyZWV0LCBEb3dudG93biBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mODUyMWI1ZGNlNzQ0MDMzYTk3NjJjNzEzMTIxMWI1MC5zZXRDb250ZW50KGh0bWxfYjNlYWU4N2UwNzBjNDcwOWEzODFlNTUwMWNhZDRkNDYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMWViOWUxMDdkYWQ1NGRjNmJlZTE5YmU1MjJkODc3MTYuYmluZFBvcHVwKHBvcHVwX2Y4NTIxYjVkY2U3NDQwMzNhOTc2MmM3MTMxMjExYjUwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2ZjZjJkNmRlYTZiMTQ5ZjY4YzhlNzQxNWFkNzdjY2RhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjUwNTcxMjAwMDAwMDEsLTc5LjM4NDU2NzVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMjFjYWEyZDQ1ZTEwNGViNzg4YmVmYTVlODVjNmViZDUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOTBiNDEzNzRjMzJmNDQ1NTlmODk1YTNkNzg0ZDkzNDkgPSAkKCc8ZGl2IGlkPSJodG1sXzkwYjQxMzc0YzMyZjQ0NTU5Zjg5NWEzZDc4NGQ5MzQ5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5BZGVsYWlkZSwgS2luZywgUmljaG1vbmQsIERvd250b3duIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzIxY2FhMmQ0NWUxMDRlYjc4OGJlZmE1ZTg1YzZlYmQ1LnNldENvbnRlbnQoaHRtbF85MGI0MTM3NGMzMmY0NDU1OWY4OTVhM2Q3ODRkOTM0OSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mY2YyZDZkZWE2YjE0OWY2OGM4ZTc0MTVhZDc3Y2NkYS5iaW5kUG9wdXAocG9wdXBfMjFjYWEyZDQ1ZTEwNGViNzg4YmVmYTVlODVjNmViZDUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNGM4MTBkNWM4ZjYxNGI1Y2I2N2RmNWJmY2Y1MmE5MzcgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDA4MTU3LC03OS4zODE3NTIyOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82OTUzNzg1M2FlMWQ0ODg3YjY4YzQxMjg3OWI2OGM0YSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lMjBiNWZlMzM5NGU0NmFkOThiZjJlOGFhYzdhZDM3ZSA9ICQoJzxkaXYgaWQ9Imh0bWxfZTIwYjVmZTMzOTRlNDZhZDk4YmYyZThhYWM3YWQzN2UiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhhcmJvdXJmcm9udCBFYXN0LCBUb3JvbnRvIElzbGFuZHMsIFVuaW9uIFN0YXRpb24sIERvd250b3duIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzY5NTM3ODUzYWUxZDQ4ODdiNjhjNDEyODc5YjY4YzRhLnNldENvbnRlbnQoaHRtbF9lMjBiNWZlMzM5NGU0NmFkOThiZjJlOGFhYzdhZDM3ZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl80YzgxMGQ1YzhmNjE0YjVjYjY3ZGY1YmZjZjUyYTkzNy5iaW5kUG9wdXAocG9wdXBfNjk1Mzc4NTNhZTFkNDg4N2I2OGM0MTI4NzliNjhjNGEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOWY1MjYzMmE3YzRjNGZkN2JiNGE5MThjNDk5MzhlZjUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDcxNzY4LC03OS4zODE1NzY0MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9kZTVkOTI3ODUwZmU0NjAyYjA1MzRjYzYxYjc4OTNjZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mYmYzYWZlOGUyNjE0Y2YyYmFkMmNlMjlhMzkyODA4MyA9ICQoJzxkaXYgaWQ9Imh0bWxfZmJmM2FmZThlMjYxNGNmMmJhZDJjZTI5YTM5MjgwODMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRlc2lnbiBFeGNoYW5nZSwgVG9yb250byBEb21pbmlvbiBDZW50cmUsIERvd250b3duIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2RlNWQ5Mjc4NTBmZTQ2MDJiMDUzNGNjNjFiNzg5M2NkLnNldENvbnRlbnQoaHRtbF9mYmYzYWZlOGUyNjE0Y2YyYmFkMmNlMjlhMzkyODA4Myk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85ZjUyNjMyYTdjNGM0ZmQ3YmI0YTkxOGM0OTkzOGVmNS5iaW5kUG9wdXAocG9wdXBfZGU1ZDkyNzg1MGZlNDYwMmIwNTM0Y2M2MWI3ODkzY2QpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMDYzNmYxOTlmODYzNGQ5YmJhOTg4MGRiYTE0M2IwYjMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDgxOTg1LC03OS4zNzk4MTY5MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81MzVhOTMyN2ZiZDA0YTE0ODU3NThhODZhMDZjNjk2YiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mMWQxMjgxZmRhY2M0Njg2YWU1Zjg2MmFkMTNjMzM3OSA9ICQoJzxkaXYgaWQ9Imh0bWxfZjFkMTI4MWZkYWNjNDY4NmFlNWY4NjJhZDEzYzMzNzkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNvbW1lcmNlIENvdXJ0LCBWaWN0b3JpYSBIb3RlbCwgRG93bnRvd24gVG9yb250bzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNTM1YTkzMjdmYmQwNGExNDg1NzU4YTg2YTA2YzY5NmIuc2V0Q29udGVudChodG1sX2YxZDEyODFmZGFjYzQ2ODZhZTVmODYyYWQxM2MzMzc5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzA2MzZmMTk5Zjg2MzRkOWJiYTk4ODBkYmExNDNiMGIzLmJpbmRQb3B1cChwb3B1cF81MzVhOTMyN2ZiZDA0YTE0ODU3NThhODZhMDZjNjk2Yik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9iNGY4NWJiYjQ1YTY0Y2QwYjZkYjU2MWU1MzdkOGJhOSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjczMzI4MjUsLTc5LjQxOTc0OTddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOGE1NTAwZjdjZDc2NGQ1ZmJiNDVhNjkwMWExYTgzYzcgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfM2M3YzU1NzlmMGQxNGNlZmFiZTdlYTdjMjk1OTIyMjEgPSAkKCc8ZGl2IGlkPSJodG1sXzNjN2M1NTc5ZjBkMTRjZWZhYmU3ZWE3YzI5NTkyMjIxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5CZWRmb3JkIFBhcmssIExhd3JlbmNlIE1hbm9yIEVhc3QsIE5vcnRoIFlvcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzhhNTUwMGY3Y2Q3NjRkNWZiYjQ1YTY5MDFhMWE4M2M3LnNldENvbnRlbnQoaHRtbF8zYzdjNTU3OWYwZDE0Y2VmYWJlN2VhN2MyOTU5MjIyMSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9iNGY4NWJiYjQ1YTY0Y2QwYjZkYjU2MWU1MzdkOGJhOS5iaW5kUG9wdXAocG9wdXBfOGE1NTAwZjdjZDc2NGQ1ZmJiNDVhNjkwMWExYTgzYzcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOWEzNjg5MGVkNDU4NDU0NGE0NGZhOTQwODJkYmY5YjkgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MTE2OTQ4LC03OS40MTY5MzU1OTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zYWY4NzljYjhhOTk0YjBlYmNlMTIzYWU2ZWIyN2E1YSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8yZjI2NzVhN2JhYzE0ZjRmODUyNTU5ZjlmY2NmZTg5NiA9ICQoJzxkaXYgaWQ9Imh0bWxfMmYyNjc1YTdiYWMxNGY0Zjg1MjU1OWY5ZmNjZmU4OTYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlJvc2VsYXduLCBDZW50cmFsIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzNhZjg3OWNiOGE5OTRiMGViY2UxMjNhZTZlYjI3YTVhLnNldENvbnRlbnQoaHRtbF8yZjI2NzVhN2JhYzE0ZjRmODUyNTU5ZjlmY2NmZTg5Nik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85YTM2ODkwZWQ0NTg0NTQ0YTQ0ZmE5NDA4MmRiZjliOS5iaW5kUG9wdXAocG9wdXBfM2FmODc5Y2I4YTk5NGIwZWJjZTEyM2FlNmViMjdhNWEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfY2VkZDRiOGU4MmMwNDkwODhhMzZhMDFjYmU2ZWFiYmIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42OTY5NDc2LC03OS40MTEzMDcyMDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82MDA2YTlhZjg1Mjc0OTQ4Yjg1ZWQ3OWFhYjNkYzA2MiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iNzAyM2Q2YTBlNTQ0MGMxYmZiODVlMjc1OGI0Y2I5OCA9ICQoJzxkaXYgaWQ9Imh0bWxfYjcwMjNkNmEwZTU0NDBjMWJmYjg1ZTI3NThiNGNiOTgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkZvcmVzdCBIaWxsIE5vcnRoLCBGb3Jlc3QgSGlsbCBXZXN0LCBDZW50cmFsIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzYwMDZhOWFmODUyNzQ5NDhiODVlZDc5YWFiM2RjMDYyLnNldENvbnRlbnQoaHRtbF9iNzAyM2Q2YTBlNTQ0MGMxYmZiODVlMjc1OGI0Y2I5OCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jZWRkNGI4ZTgyYzA0OTA4OGEzNmEwMWNiZTZlYWJiYi5iaW5kUG9wdXAocG9wdXBfNjAwNmE5YWY4NTI3NDk0OGI4NWVkNzlhYWIzZGMwNjIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYjdiNTYwZmJlMTliNDUyMGJkOGJiODA5NmNjZWQwNWYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NzI3MDk3LC03OS40MDU2Nzg0MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80ZjRjZjEwNmU5MjE0MzNiYjMyMGVhOWUwOTMwMzRiZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xMjVkZmMzYTBiZDU0NzExYjY1ZDM1ZDllMDkyYjFhYiA9ICQoJzxkaXYgaWQ9Imh0bWxfMTI1ZGZjM2EwYmQ1NDcxMWI2NWQzNWQ5ZTA5MmIxYWIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlRoZSBBbm5leCwgTm9ydGggTWlkdG93biwgWW9ya3ZpbGxlLCBDZW50cmFsIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzRmNGNmMTA2ZTkyMTQzM2JiMzIwZWE5ZTA5MzAzNGJmLnNldENvbnRlbnQoaHRtbF8xMjVkZmMzYTBiZDU0NzExYjY1ZDM1ZDllMDkyYjFhYik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9iN2I1NjBmYmUxOWI0NTIwYmQ4YmI4MDk2Y2NlZDA1Zi5iaW5kUG9wdXAocG9wdXBfNGY0Y2YxMDZlOTIxNDMzYmIzMjBlYTllMDkzMDM0YmYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfODlhZjMyOWVkNTc1NDdmODhjZDNhZGQ4YWM3YzVjMWMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NjI2OTU2LC03OS40MDAwNDkzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzI0YWY0MjE2MTcyYjRjNmU4NjE5YmIzOGIxMzM2Y2NjID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2IxZWI0Njg0MjVhZjQ2YTk4ZTJlY2IzYmFiMWNkZGJhID0gJCgnPGRpdiBpZD0iaHRtbF9iMWViNDY4NDI1YWY0NmE5OGUyZWNiM2JhYjFjZGRiYSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SGFyYm9yZCwgVW5pdmVyc2l0eSBvZiBUb3JvbnRvLCBEb3dudG93biBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yNGFmNDIxNjE3MmI0YzZlODYxOWJiMzhiMTMzNmNjYy5zZXRDb250ZW50KGh0bWxfYjFlYjQ2ODQyNWFmNDZhOThlMmVjYjNiYWIxY2RkYmEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODlhZjMyOWVkNTc1NDdmODhjZDNhZGQ4YWM3YzVjMWMuYmluZFBvcHVwKHBvcHVwXzI0YWY0MjE2MTcyYjRjNmU4NjE5YmIzOGIxMzM2Y2NjKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzVmZGQ0NjAzZGNmNDQxNWFiYTNkMmZmZjU5ZmJmNmUyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjUzMjA1NywtNzkuNDAwMDQ5M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mYzJiMGE4M2Y5MWI0MWVlODAyOGEwNDlkNTZmYmU5ZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80YThjNWFiODZhMzY0YmJjYjAzMDUwOWIyNGIwOTYyNCA9ICQoJzxkaXYgaWQ9Imh0bWxfNGE4YzVhYjg2YTM2NGJiY2IwMzA1MDliMjRiMDk2MjQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNoaW5hdG93biwgR3JhbmdlIFBhcmssIEtlbnNpbmd0b24gTWFya2V0LCBEb3dudG93biBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mYzJiMGE4M2Y5MWI0MWVlODAyOGEwNDlkNTZmYmU5ZS5zZXRDb250ZW50KGh0bWxfNGE4YzVhYjg2YTM2NGJiY2IwMzA1MDliMjRiMDk2MjQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNWZkZDQ2MDNkY2Y0NDE1YWJhM2QyZmZmNTlmYmY2ZTIuYmluZFBvcHVwKHBvcHVwX2ZjMmIwYTgzZjkxYjQxZWU4MDI4YTA0OWQ1NmZiZTllKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzIyM2IwOWZjNmRiYjQ5ODA4YzNiYWI3MThlZmIwZjFkID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjI4OTQ2NywtNzkuMzk0NDE5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zYmNjZjc5Y2VhMWI0ZTkyOGFjOThlZDMzY2EzYWZkZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF84YjE2YWExZDk0NTQ0NWVlOWJhNzEyMTY3YzRiNmQ1NSA9ICQoJzxkaXYgaWQ9Imh0bWxfOGIxNmFhMWQ5NDU0NDVlZTliYTcxMjE2N2M0YjZkNTUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNOIFRvd2VyLCBCYXRodXJzdCBRdWF5LCBJc2xhbmQgYWlycG9ydCwgSGFyYm91cmZyb250IFdlc3QsIEtpbmcgYW5kIFNwYWRpbmEsIFJhaWx3YXkgTGFuZHMsIFNvdXRoIE5pYWdhcmEsIERvd250b3duIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzNiY2NmNzljZWExYjRlOTI4YWM5OGVkMzNjYTNhZmRkLnNldENvbnRlbnQoaHRtbF84YjE2YWExZDk0NTQ0NWVlOWJhNzEyMTY3YzRiNmQ1NSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8yMjNiMDlmYzZkYmI0OTgwOGMzYmFiNzE4ZWZiMGYxZC5iaW5kUG9wdXAocG9wdXBfM2JjY2Y3OWNlYTFiNGU5MjhhYzk4ZWQzM2NhM2FmZGQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNDA3OWM3Zjk2MmNhNDQwOGIwZGMyZTMwM2Y1NDE5NTYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDY0MzUyLC03OS4zNzQ4NDU5OTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iNjA1Mjk3MGNhNmI0ZjQzODVmMjhlYjQ4ODY4Y2RjNyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF84NmU1Y2MyMWI3NjQ0N2QzYTRlYzFiYTRiODcyYjMzZiA9ICQoJzxkaXYgaWQ9Imh0bWxfODZlNWNjMjFiNzY0NDdkM2E0ZWMxYmE0Yjg3MmIzM2YiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlN0biBBIFBPIEJveGVzIDI1IFRoZSBFc3BsYW5hZGUsIERvd250b3duIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2I2MDUyOTcwY2E2YjRmNDM4NWYyOGViNDg4NjhjZGM3LnNldENvbnRlbnQoaHRtbF84NmU1Y2MyMWI3NjQ0N2QzYTRlYzFiYTRiODcyYjMzZik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl80MDc5YzdmOTYyY2E0NDA4YjBkYzJlMzAzZjU0MTk1Ni5iaW5kUG9wdXAocG9wdXBfYjYwNTI5NzBjYTZiNGY0Mzg1ZjI4ZWI0ODg2OGNkYzcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNzhmN2E5M2QyYmVmNDg3MGE1YzFiZmUwMDQ0MmI1NWMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDg0MjkyLC03OS4zODIyODAyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzZmYWI4ZDZkZmU3MjRiNGM5NDgxNjhlNTg2ZGYxYjBmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzBhNTYxNWRhYmMxNTQwMzQ4ZWQ1OGY4ZTY0Mzk5ZTI1ID0gJCgnPGRpdiBpZD0iaHRtbF8wYTU2MTVkYWJjMTU0MDM0OGVkNThmOGU2NDM5OWUyNSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Rmlyc3QgQ2FuYWRpYW4gUGxhY2UsIFVuZGVyZ3JvdW5kIGNpdHksIERvd250b3duIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzZmYWI4ZDZkZmU3MjRiNGM5NDgxNjhlNTg2ZGYxYjBmLnNldENvbnRlbnQoaHRtbF8wYTU2MTVkYWJjMTU0MDM0OGVkNThmOGU2NDM5OWUyNSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83OGY3YTkzZDJiZWY0ODcwYTVjMWJmZTAwNDQyYjU1Yy5iaW5kUG9wdXAocG9wdXBfNmZhYjhkNmRmZTcyNGI0Yzk0ODE2OGU1ODZkZjFiMGYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZGMzZDgxMjYzNzVlNDI2YmFkOWUxMjJlNWRhODUwNDYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MTg1MTc5OTk5OTk5OTYsLTc5LjQ2NDc2MzI5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzc0NjY0N2IwMDhmODQ5MmU5MjkyZGYzODExNTI2MDg0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzhlNTllZDhjMzQyZjQ1MmM5ZDcxNzJlNTE5N2Q0NTU5ID0gJCgnPGRpdiBpZD0iaHRtbF84ZTU5ZWQ4YzM0MmY0NTJjOWQ3MTcyZTUxOTdkNDU1OSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TGF3cmVuY2UgSGVpZ2h0cywgTGF3cmVuY2UgTWFub3IsIE5vcnRoIFlvcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzc0NjY0N2IwMDhmODQ5MmU5MjkyZGYzODExNTI2MDg0LnNldENvbnRlbnQoaHRtbF84ZTU5ZWQ4YzM0MmY0NTJjOWQ3MTcyZTUxOTdkNDU1OSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9kYzNkODEyNjM3NWU0MjZiYWQ5ZTEyMmU1ZGE4NTA0Ni5iaW5kUG9wdXAocG9wdXBfNzQ2NjQ3YjAwOGY4NDkyZTkyOTJkZjM4MTE1MjYwODQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNDU2YTZlNzc0YzBiNGM1OGI4MWIzMDllN2RhNmI1NDAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MDk1NzcsLTc5LjQ0NTA3MjU5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzhiOWVhOTE1ZjM1ODRmZDc5MjVkZTI2OTdhYTMzMmIzID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzZhNzdiYmUyMTA2MDQ0ZDdiMzk5YWQzYWYwMDRiYzhlID0gJCgnPGRpdiBpZD0iaHRtbF82YTc3YmJlMjEwNjA0NGQ3YjM5OWFkM2FmMDA0YmM4ZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+R2xlbmNhaXJuLCBOb3J0aCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84YjllYTkxNWYzNTg0ZmQ3OTI1ZGUyNjk3YWEzMzJiMy5zZXRDb250ZW50KGh0bWxfNmE3N2JiZTIxMDYwNDRkN2IzOTlhZDNhZjAwNGJjOGUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNDU2YTZlNzc0YzBiNGM1OGI4MWIzMDllN2RhNmI1NDAuYmluZFBvcHVwKHBvcHVwXzhiOWVhOTE1ZjM1ODRmZDc5MjVkZTI2OTdhYTMzMmIzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2JlZGRkMWRhM2MzMDQxOTFhMjUzMmQ2NjY0MDgzZTA0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjkzNzgxMywtNzkuNDI4MTkxNDAwMDAwMDJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOGM0Nzc4MzI5ZWE2NDMxNmI3N2NhMjUyODAxZTUyMzYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZDIyNDA3MjIxYzFiNDdjZWIxMzlkZTJiMzkwMDQ1ODkgPSAkKCc8ZGl2IGlkPSJodG1sX2QyMjQwNzIyMWMxYjQ3Y2ViMTM5ZGUyYjM5MDA0NTg5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IdW1ld29vZC1DZWRhcnZhbGUsIFlvcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzhjNDc3ODMyOWVhNjQzMTZiNzdjYTI1MjgwMWU1MjM2LnNldENvbnRlbnQoaHRtbF9kMjI0MDcyMjFjMWI0N2NlYjEzOWRlMmIzOTAwNDU4OSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9iZWRkZDFkYTNjMzA0MTkxYTI1MzJkNjY2NDA4M2UwNC5iaW5kUG9wdXAocG9wdXBfOGM0Nzc4MzI5ZWE2NDMxNmI3N2NhMjUyODAxZTUyMzYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZmJiMjc1OTEwNGNiNDg3MmIyNDE5ODU5ZTNlMGM4YTMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42ODkwMjU2LC03OS40NTM1MTJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfM2NhZmZkMGMwODhiNDI3YjhhMTAzZDBkYjJhNjEwZTQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfM2UxZDI0NDgyZDg1NDY5OWFjZDBhMDczYzAxM2VjYjIgPSAkKCc8ZGl2IGlkPSJodG1sXzNlMWQyNDQ4MmQ4NTQ2OTlhY2QwYTA3M2MwMTNlY2IyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DYWxlZG9uaWEtRmFpcmJhbmtzLCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zY2FmZmQwYzA4OGI0MjdiOGExMDNkMGRiMmE2MTBlNC5zZXRDb250ZW50KGh0bWxfM2UxZDI0NDgyZDg1NDY5OWFjZDBhMDczYzAxM2VjYjIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZmJiMjc1OTEwNGNiNDg3MmIyNDE5ODU5ZTNlMGM4YTMuYmluZFBvcHVwKHBvcHVwXzNjYWZmZDBjMDg4YjQyN2I4YTEwM2QwZGIyYTYxMGU0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzFmMWM0NDBiOGI1YzRmZWZiMTUxMzI3MWI5Y2YwNDlmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjY5NTQyLC03OS40MjI1NjM3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzYxMDRjMDE4NjhjYzRjZWFhNWIzYzUxZWY3NGMwZWE5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2FhZThmNGJmZmJkMDQ5NDk5YTY1NTU2NDNkZWNiOGM2ID0gJCgnPGRpdiBpZD0iaHRtbF9hYWU4ZjRiZmZiZDA0OTQ5OWE2NTU1NjQzZGVjYjhjNiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q2hyaXN0aWUsIERvd250b3duIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzYxMDRjMDE4NjhjYzRjZWFhNWIzYzUxZWY3NGMwZWE5LnNldENvbnRlbnQoaHRtbF9hYWU4ZjRiZmZiZDA0OTQ5OWE2NTU1NjQzZGVjYjhjNik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8xZjFjNDQwYjhiNWM0ZmVmYjE1MTMyNzFiOWNmMDQ5Zi5iaW5kUG9wdXAocG9wdXBfNjEwNGMwMTg2OGNjNGNlYWE1YjNjNTFlZjc0YzBlYTkpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfODBjOThmMGRlMjFhNDlkYmFmNmVlMzgwNGEyOTQ3YzIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NjkwMDUxMDAwMDAwMSwtNzkuNDQyMjU5M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9hZWFmMWNhNGRjMjA0NTk1YTljZTljZGJhOWY3OTE5NiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8yMmNlMjlmNjhjZGU0ODMxYjRhMDlkYzc0MTZlYjk1MCA9ICQoJzxkaXYgaWQ9Imh0bWxfMjJjZTI5ZjY4Y2RlNDgzMWI0YTA5ZGM3NDE2ZWI5NTAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRvdmVyY291cnQgVmlsbGFnZSwgRHVmZmVyaW4sIFdlc3QgVG9yb250bzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYWVhZjFjYTRkYzIwNDU5NWE5Y2U5Y2RiYTlmNzkxOTYuc2V0Q29udGVudChodG1sXzIyY2UyOWY2OGNkZTQ4MzFiNGEwOWRjNzQxNmViOTUwKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzgwYzk4ZjBkZTIxYTQ5ZGJhZjZlZTM4MDRhMjk0N2MyLmJpbmRQb3B1cChwb3B1cF9hZWFmMWNhNGRjMjA0NTk1YTljZTljZGJhOWY3OTE5Nik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kYWNiNzQzM2M2Y2Y0ZTk0OTg0YzljMzY4MDliZDA1OCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY0NzkyNjcwMDAwMDAwNiwtNzkuNDE5NzQ5N10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zZGYzMmM5ZGVlY2M0ZDg4YjkyNzM0ZGI3ODUyNWExMCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iNDhhNjk0ODE4NDQ0ZDYzYTgyZmM2Y2UxYmExN2E1OSA9ICQoJzxkaXYgaWQ9Imh0bWxfYjQ4YTY5NDgxODQ0NGQ2M2E4MmZjNmNlMWJhMTdhNTkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkxpdHRsZSBQb3J0dWdhbCwgVHJpbml0eSwgV2VzdCBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zZGYzMmM5ZGVlY2M0ZDg4YjkyNzM0ZGI3ODUyNWExMC5zZXRDb250ZW50KGh0bWxfYjQ4YTY5NDgxODQ0NGQ2M2E4MmZjNmNlMWJhMTdhNTkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZGFjYjc0MzNjNmNmNGU5NDk4NGM5YzM2ODA5YmQwNTguYmluZFBvcHVwKHBvcHVwXzNkZjMyYzlkZWVjYzRkODhiOTI3MzRkYjc4NTI1YTEwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzUyZTkxNTNiNTdlMzRiNDc5ZWY2YjM4N2ZlOTc4Mzg4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjM2ODQ3MiwtNzkuNDI4MTkxNDAwMDAwMDJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMDFmOTA5YzgxZDdhNDQyZmI3M2FlNGIwN2QyMGM5NzggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMWJjYmU1NjU4OGVjNGVlNWJhMzM1YmIyMGY0Y2EzNzYgPSAkKCc8ZGl2IGlkPSJodG1sXzFiY2JlNTY1ODhlYzRlZTViYTMzNWJiMjBmNGNhMzc2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Ccm9ja3RvbiwgRXhoaWJpdGlvbiBQbGFjZSwgUGFya2RhbGUgVmlsbGFnZSwgV2VzdCBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8wMWY5MDljODFkN2E0NDJmYjczYWU0YjA3ZDIwYzk3OC5zZXRDb250ZW50KGh0bWxfMWJjYmU1NjU4OGVjNGVlNWJhMzM1YmIyMGY0Y2EzNzYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNTJlOTE1M2I1N2UzNGI0NzllZjZiMzg3ZmU5NzgzODguYmluZFBvcHVwKHBvcHVwXzAxZjkwOWM4MWQ3YTQ0MmZiNzNhZTRiMDdkMjBjOTc4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzA1NDllMDg5ZGU3YjRlYTRhNTY0M2Y0ZTM2OTRkMzk4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzEzNzU2MjAwMDAwMDA2LC03OS40OTAwNzM4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzhhZmIwNDBhMDI3ZjQzZjc5ZTJlN2RmOGU0YTdlY2VlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzdjZDI1NDZmNTk3OTQ5ZjU4MDQ0OTM4ZjdjMTE2M2MxID0gJCgnPGRpdiBpZD0iaHRtbF83Y2QyNTQ2ZjU5Nzk0OWY1ODA0NDkzOGY3YzExNjNjMSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RG93bnN2aWV3LCBOb3J0aCBQYXJrLCBVcHdvb2QgUGFyaywgTm9ydGggWW9yazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOGFmYjA0MGEwMjdmNDNmNzllMmU3ZGY4ZTRhN2VjZWUuc2V0Q29udGVudChodG1sXzdjZDI1NDZmNTk3OTQ5ZjU4MDQ0OTM4ZjdjMTE2M2MxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzA1NDllMDg5ZGU3YjRlYTRhNTY0M2Y0ZTM2OTRkMzk4LmJpbmRQb3B1cChwb3B1cF84YWZiMDQwYTAyN2Y0M2Y3OWUyZTdkZjhlNGE3ZWNlZSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kMTczNzM3MTBkZTc0Y2JmOTZjMTYzNmE2OGY1YWIyZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY5MTExNTgsLTc5LjQ3NjAxMzI5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzU0MGRkNDI3YzQ2NTRlOThiNmI4NTRiN2FjY2RiNTI1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzEzNTExMTk4Y2QyNDQ1ZDliMjMxYjdiMDJlZGRmZmRiID0gJCgnPGRpdiBpZD0iaHRtbF8xMzUxMTE5OGNkMjQ0NWQ5YjIzMWI3YjAyZWRkZmZkYiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RGVsIFJheSwgS2VlbGVzZGFsZSwgTW91bnQgRGVubmlzLCBTaWx2ZXJ0aG9ybiwgWW9yazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNTQwZGQ0MjdjNDY1NGU5OGI2Yjg1NGI3YWNjZGI1MjUuc2V0Q29udGVudChodG1sXzEzNTExMTk4Y2QyNDQ1ZDliMjMxYjdiMDJlZGRmZmRiKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2QxNzM3MzcxMGRlNzRjYmY5NmMxNjM2YTY4ZjVhYjJmLmJpbmRQb3B1cChwb3B1cF81NDBkZDQyN2M0NjU0ZTk4YjZiODU0YjdhY2NkYjUyNSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9iNjQ2ZjYwMDNiOTY0Y2M1Yjk1NzMzNmE4YTY2N2Q4OCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY3MzE4NTI5OTk5OTk5LC03OS40ODcyNjE5MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82NDYwOTUyODg2YTU0NGUzOWU1M2UwMTI2ZmM2MmEzYSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iMzk2N2U3MDllZjU0ZDFhODM1YzFjM2JjNWYxYWE5YiA9ICQoJzxkaXYgaWQ9Imh0bWxfYjM5NjdlNzA5ZWY1NGQxYTgzNWMxYzNiYzVmMWFhOWIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlRoZSBKdW5jdGlvbiBOb3J0aCwgUnVubnltZWRlLCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82NDYwOTUyODg2YTU0NGUzOWU1M2UwMTI2ZmM2MmEzYS5zZXRDb250ZW50KGh0bWxfYjM5NjdlNzA5ZWY1NGQxYTgzNWMxYzNiYzVmMWFhOWIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYjY0NmY2MDAzYjk2NGNjNWI5NTczMzZhOGE2NjdkODguYmluZFBvcHVwKHBvcHVwXzY0NjA5NTI4ODZhNTQ0ZTM5ZTUzZTAxMjZmYzYyYTNhKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzg3NzBiOWQxMTZkNjQ3YTlhYWQyMTFmZTJkYjBiNWQ1ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjYxNjA4MywtNzkuNDY0NzYzMjk5OTk5OTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfODczY2EwYTI5NTMyNDE5NmE1MDdmN2ZjYTgwNjlmZWEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfM2FhZTc3NjViMDI0NDQzODgzMTRhMzBiYWNjY2NjYjMgPSAkKCc8ZGl2IGlkPSJodG1sXzNhYWU3NzY1YjAyNDQ0Mzg4MzE0YTMwYmFjY2NjY2IzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IaWdoIFBhcmssIFRoZSBKdW5jdGlvbiBTb3V0aCwgV2VzdCBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84NzNjYTBhMjk1MzI0MTk2YTUwN2Y3ZmNhODA2OWZlYS5zZXRDb250ZW50KGh0bWxfM2FhZTc3NjViMDI0NDQzODgzMTRhMzBiYWNjY2NjYjMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODc3MGI5ZDExNmQ2NDdhOWFhZDIxMWZlMmRiMGI1ZDUuYmluZFBvcHVwKHBvcHVwXzg3M2NhMGEyOTUzMjQxOTZhNTA3ZjdmY2E4MDY5ZmVhKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2JjZTVhMjg0M2Q1ODRlMjE4Njc3YmRlODdhNmJiMTY0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjQ4OTU5NywtNzkuNDU2MzI1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzJhMjRmNzg1MWE3YzQ5MGFiMWQ0ZTlhNjg1YTUwYTExID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzE2M2UzMjk2YjVmODQ3ODdhYzFlMjBiNGRlNjZkMmRkID0gJCgnPGRpdiBpZD0iaHRtbF8xNjNlMzI5NmI1Zjg0Nzg3YWMxZTIwYjRkZTY2ZDJkZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UGFya2RhbGUsIFJvbmNlc3ZhbGxlcywgV2VzdCBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yYTI0Zjc4NTFhN2M0OTBhYjFkNGU5YTY4NWE1MGExMS5zZXRDb250ZW50KGh0bWxfMTYzZTMyOTZiNWY4NDc4N2FjMWUyMGI0ZGU2NmQyZGQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYmNlNWEyODQzZDU4NGUyMTg2NzdiZGU4N2E2YmIxNjQuYmluZFBvcHVwKHBvcHVwXzJhMjRmNzg1MWE3YzQ5MGFiMWQ0ZTlhNjg1YTUwYTExKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzcwZGU5ZTBjZDYxNDRjNmViYTdlYTA3NWEzMjRjYjEyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjUxNTcwNiwtNzkuNDg0NDQ5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9kMDQ5ODM1NmY0OTc0OGFmYTBlY2NlZjhiYTZhYTI2NCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8zNTQ5MTg0MTQzZGE0MjAzODBmMjhkY2VkMWE1ZjBjMCA9ICQoJzxkaXYgaWQ9Imh0bWxfMzU0OTE4NDE0M2RhNDIwMzgwZjI4ZGNlZDFhNWYwYzAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlJ1bm55bWVkZSwgU3dhbnNlYSwgV2VzdCBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9kMDQ5ODM1NmY0OTc0OGFmYTBlY2NlZjhiYTZhYTI2NC5zZXRDb250ZW50KGh0bWxfMzU0OTE4NDE0M2RhNDIwMzgwZjI4ZGNlZDFhNWYwYzApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNzBkZTllMGNkNjE0NGM2ZWJhN2VhMDc1YTMyNGNiMTIuYmluZFBvcHVwKHBvcHVwX2QwNDk4MzU2ZjQ5NzQ4YWZhMGVjY2VmOGJhNmFhMjY0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzY2ZjQ4Y2JkNzlhNzQyZDE4MGNkNDAzMzU3YzEyNDAzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjYyMzAxNSwtNzkuMzg5NDkzOF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83Y2JjNTZlNjg4NmE0NjNhODI4MDEyY2Y5MjFkMjJjNiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8wMzlmNGMyOTdiMjc0ZGEzYTgwZTI5ZDJjNTE2MjIzYyA9ICQoJzxkaXYgaWQ9Imh0bWxfMDM5ZjRjMjk3YjI3NGRhM2E4MGUyOWQyYzUxNjIyM2MiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlF1ZWVuJiMzOTtzIFBhcmssIFF1ZWVuJiMzOTtzIFBhcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzdjYmM1NmU2ODg2YTQ2M2E4MjgwMTJjZjkyMWQyMmM2LnNldENvbnRlbnQoaHRtbF8wMzlmNGMyOTdiMjc0ZGEzYTgwZTI5ZDJjNTE2MjIzYyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82NmY0OGNiZDc5YTc0MmQxODBjZDQwMzM1N2MxMjQwMy5iaW5kUG9wdXAocG9wdXBfN2NiYzU2ZTY4ODZhNDYzYTgyODAxMmNmOTIxZDIyYzYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOGYzN2E5MzRhM2FjNDViMThhMTc5NjkzNjEyMDA4MDAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42MzY5NjU2LC03OS42MTU4MTg5OTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mNjE4MWY3NTM3MDM0YjlkYjgzNGI5NDgyZDI5MmMwZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xN2E0NmQ0MDZmNTI0OTAzYmMzMTYxZGYwMGUyYjI4MSA9ICQoJzxkaXYgaWQ9Imh0bWxfMTdhNDZkNDA2ZjUyNDkwM2JjMzE2MWRmMDBlMmIyODEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNhbmFkYSBQb3N0IEdhdGV3YXkgUHJvY2Vzc2luZyBDZW50cmUsIE1pc3Npc3NhdWdhPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mNjE4MWY3NTM3MDM0YjlkYjgzNGI5NDgyZDI5MmMwZS5zZXRDb250ZW50KGh0bWxfMTdhNDZkNDA2ZjUyNDkwM2JjMzE2MWRmMDBlMmIyODEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOGYzN2E5MzRhM2FjNDViMThhMTc5NjkzNjEyMDA4MDAuYmluZFBvcHVwKHBvcHVwX2Y2MTgxZjc1MzcwMzRiOWRiODM0Yjk0ODJkMjkyYzBlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzg5NWVlMDU3MTU1YjQ4ODdhYjNjYzAzOGMxZjA1NmE1ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjYyNzQzOSwtNzkuMzIxNTU4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2VhNWEyZGVkNGNmMzRjZjFiNmQzNGZmZjUzMDM5YTllID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2ZlM2ZlNzU4MzhjNDRmMzg4M2M2MzJkMTIwNzg5M2I1ID0gJCgnPGRpdiBpZD0iaHRtbF9mZTNmZTc1ODM4YzQ0ZjM4ODNjNjMyZDEyMDc4OTNiNSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QnVzaW5lc3MgUmVwbHkgTWFpbCBQcm9jZXNzaW5nIENlbnRyZSA5NjkgRWFzdGVybiwgRWFzdCBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9lYTVhMmRlZDRjZjM0Y2YxYjZkMzRmZmY1MzAzOWE5ZS5zZXRDb250ZW50KGh0bWxfZmUzZmU3NTgzOGM0NGYzODgzYzYzMmQxMjA3ODkzYjUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODk1ZWUwNTcxNTViNDg4N2FiM2NjMDM4YzFmMDU2YTUuYmluZFBvcHVwKHBvcHVwX2VhNWEyZGVkNGNmMzRjZjFiNmQzNGZmZjUzMDM5YTllKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzU0Y2Y3OTNmMjY3NDRmMmE5ZDIyYTAxY2VhNTI0YjlmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjA1NjQ2NiwtNzkuNTAxMzIwNzAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMTc4OGRmZTEyMjk1NGVjNmFhOWNjNDMwZjU1ZGQ5Y2IgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOTYxNzIxOTE3MTI1NGQyMjkwZjdlNTUxNTM0MzFmZDYgPSAkKCc8ZGl2IGlkPSJodG1sXzk2MTcyMTkxNzEyNTRkMjI5MGY3ZTU1MTUzNDMxZmQ2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IdW1iZXIgQmF5IFNob3JlcywgTWltaWNvIFNvdXRoLCBOZXcgVG9yb250bywgRXRvYmljb2tlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8xNzg4ZGZlMTIyOTU0ZWM2YWE5Y2M0MzBmNTVkZDljYi5zZXRDb250ZW50KGh0bWxfOTYxNzIxOTE3MTI1NGQyMjkwZjdlNTUxNTM0MzFmZDYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNTRjZjc5M2YyNjc0NGYyYTlkMjJhMDFjZWE1MjRiOWYuYmluZFBvcHVwKHBvcHVwXzE3ODhkZmUxMjI5NTRlYzZhYTljYzQzMGY1NWRkOWNiKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzRjNmFkNmYwNDAzNDQzMzNhMzQwYTdmMGYwODAzNzEwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjAyNDEzNzAwMDAwMDEsLTc5LjU0MzQ4NDA5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzYzNzk0MmJkOTBmZjQwZGQ4NmJhYjgzNjQ0ZGViYTE3ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzJhYmM2MmE0ZDQ2ODQ1NTU5NDYzMzBhZmRkNTFjY2UxID0gJCgnPGRpdiBpZD0iaHRtbF8yYWJjNjJhNGQ0Njg0NTU1OTQ2MzMwYWZkZDUxY2NlMSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QWxkZXJ3b29kLCBMb25nIEJyYW5jaCwgRXRvYmljb2tlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82Mzc5NDJiZDkwZmY0MGRkODZiYWI4MzY0NGRlYmExNy5zZXRDb250ZW50KGh0bWxfMmFiYzYyYTRkNDY4NDU1NTk0NjMzMGFmZGQ1MWNjZTEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNGM2YWQ2ZjA0MDM0NDMzM2EzNDBhN2YwZjA4MDM3MTAuYmluZFBvcHVwKHBvcHVwXzYzNzk0MmJkOTBmZjQwZGQ4NmJhYjgzNjQ0ZGViYTE3KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2JiODFjY2NkMzE4MzRmMGRhMTUyYTkyMDdmMjNiZGI2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjUzNjUzNjAwMDAwMDA1LC03OS41MDY5NDM2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzU0NGE1OGUyNTVmNTQ4ODI4NjZhNzRmNTg5YjIxM2ZiID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzI5MWRhODdlM2FhYTQyNjU5MzMzNWRhMjMwNGRlNDc0ID0gJCgnPGRpdiBpZD0iaHRtbF8yOTFkYTg3ZTNhYWE0MjY1OTMzMzVkYTIzMDRkZTQ3NCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VGhlIEtpbmdzd2F5LCBNb250Z29tZXJ5IFJvYWQsIE9sZCBNaWxsIE5vcnRoLCBFdG9iaWNva2U8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzU0NGE1OGUyNTVmNTQ4ODI4NjZhNzRmNTg5YjIxM2ZiLnNldENvbnRlbnQoaHRtbF8yOTFkYTg3ZTNhYWE0MjY1OTMzMzVkYTIzMDRkZTQ3NCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9iYjgxY2NjZDMxODM0ZjBkYTE1MmE5MjA3ZjIzYmRiNi5iaW5kUG9wdXAocG9wdXBfNTQ0YTU4ZTI1NWY1NDg4Mjg2NmE3NGY1ODliMjEzZmIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNzA5YTQyNzI3ZTNjNDViNmFjMjAzOTVlZmMxZDgwOGMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42MzYyNTc5LC03OS40OTg1MDkwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zMjg0ZGQyMDUzYjc0OWU1YTI1ZjhiNGRhNWRlOTZkNSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mNzM2MGM2NmFmYzE0ZTgxYTcyYjNmNGRlZmFmM2Q5NyA9ICQoJzxkaXYgaWQ9Imh0bWxfZjczNjBjNjZhZmMxNGU4MWE3MmIzZjRkZWZhZjNkOTciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkh1bWJlciBCYXksIEtpbmcmIzM5O3MgTWlsbCBQYXJrLCBLaW5nc3dheSBQYXJrIFNvdXRoIEVhc3QsIE1pbWljbyBORSwgT2xkIE1pbGwgU291dGgsIFRoZSBRdWVlbnN3YXkgRWFzdCwgUm95YWwgWW9yayBTb3V0aCBFYXN0LCBTdW5ueWxlYSwgRXRvYmljb2tlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zMjg0ZGQyMDUzYjc0OWU1YTI1ZjhiNGRhNWRlOTZkNS5zZXRDb250ZW50KGh0bWxfZjczNjBjNjZhZmMxNGU4MWE3MmIzZjRkZWZhZjNkOTcpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNzA5YTQyNzI3ZTNjNDViNmFjMjAzOTVlZmMxZDgwOGMuYmluZFBvcHVwKHBvcHVwXzMyODRkZDIwNTNiNzQ5ZTVhMjVmOGI0ZGE1ZGU5NmQ1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2EyYWUzNGI1MDQ1YTQwNTJiYWJhN2Y5OWNiYzRlYjJjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjI4ODQwOCwtNzkuNTIwOTk5NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOTA0MWFlNThjMjFiNGRlYjhkMjAzMzhkMDhlODc4ODQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMTQxMzAzNjIyZmUyNDExZTgzMDJiNzYzZGNjMWQ0ZDkgPSAkKCc8ZGl2IGlkPSJodG1sXzE0MTMwMzYyMmZlMjQxMWU4MzAyYjc2M2RjYzFkNGQ5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5LaW5nc3dheSBQYXJrIFNvdXRoIFdlc3QsIE1pbWljbyBOVywgVGhlIFF1ZWVuc3dheSBXZXN0LCBSb3lhbCBZb3JrIFNvdXRoIFdlc3QsIFNvdXRoIG9mIEJsb29yLCBFdG9iaWNva2U8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzkwNDFhZTU4YzIxYjRkZWI4ZDIwMzM4ZDA4ZTg3ODg0LnNldENvbnRlbnQoaHRtbF8xNDEzMDM2MjJmZTI0MTFlODMwMmI3NjNkY2MxZDRkOSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9hMmFlMzRiNTA0NWE0MDUyYmFiYTdmOTljYmM0ZWIyYy5iaW5kUG9wdXAocG9wdXBfOTA0MWFlNThjMjFiNGRlYjhkMjAzMzhkMDhlODc4ODQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfN2FkYTkyMjg4YzRjNDhlNmEzMGRkMGFlNTkxNDYyYWYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42Njc4NTU2LC03OS41MzIyNDI0MDAwMDAwMl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF85NzA3ZjdlMWFmMTE0ZmZiYjcyMWQ1YzZhMDZjZjU1ZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83MTBlYjlmMjYxODk0NDEyYmZmZTQ1YThhMGU3MDk4ZCA9ICQoJzxkaXYgaWQ9Imh0bWxfNzEwZWI5ZjI2MTg5NDQxMmJmZmU0NWE4YTBlNzA5OGQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlF1ZWVuJiMzOTtzIFBhcmssIERvd250b3duIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzk3MDdmN2UxYWYxMTRmZmJiNzIxZDVjNmEwNmNmNTVlLnNldENvbnRlbnQoaHRtbF83MTBlYjlmMjYxODk0NDEyYmZmZTQ1YThhMGU3MDk4ZCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83YWRhOTIyODhjNGM0OGU2YTMwZGQwYWU1OTE0NjJhZi5iaW5kUG9wdXAocG9wdXBfOTcwN2Y3ZTFhZjExNGZmYmI3MjFkNWM2YTA2Y2Y1NWUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNzAxZTBlZWNkNDQ5NGU0OTljZGZkYWFjODFlZGI3YWUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NTA5NDMyLC03OS41NTQ3MjQ0MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yMGI2OGE5YjNiMjk0NTMwYWEwYzYxZWJiZDM5MzBhYSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9kOTAwYjdkYjMwNTQ0ODQ5YjEyNGQ1ODQ0YjVjNmVhYiA9ICQoJzxkaXYgaWQ9Imh0bWxfZDkwMGI3ZGIzMDU0NDg0OWIxMjRkNTg0NGI1YzZlYWIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNsb3ZlcmRhbGUsIElzbGluZ3RvbiwgTWFydGluIEdyb3ZlLCBQcmluY2VzcyBHYXJkZW5zLCBXZXN0IERlYW5lIFBhcmssIEV0b2JpY29rZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMjBiNjhhOWIzYjI5NDUzMGFhMGM2MWViYmQzOTMwYWEuc2V0Q29udGVudChodG1sX2Q5MDBiN2RiMzA1NDQ4NDliMTI0ZDU4NDRiNWM2ZWFiKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzcwMWUwZWVjZDQ0OTRlNDk5Y2RmZGFhYzgxZWRiN2FlLmJpbmRQb3B1cChwb3B1cF8yMGI2OGE5YjNiMjk0NTMwYWEwYzYxZWJiZDM5MzBhYSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84YTgwYjE4OGEyMGU0MzUyOWU5MTY1YjU3NWUyOWMwMSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY0MzUxNTIsLTc5LjU3NzIwMDc5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzdiOTA3ODA0NTgxMDQzYmM4MzA4YWQ2YmRhN2NhZGNlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzJhYjBlMWRkNjYwODQ1Mzk5ZmQzZmRiZDBlZDRlNWUwID0gJCgnPGRpdiBpZD0iaHRtbF8yYWIwZTFkZDY2MDg0NTM5OWZkM2ZkYmQwZWQ0ZTVlMCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Qmxvb3JkYWxlIEdhcmRlbnMsIEVyaW5nYXRlLCBNYXJrbGFuZCBXb29kLCBPbGQgQnVybmhhbXRob3JwZSwgRXRvYmljb2tlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83YjkwNzgwNDU4MTA0M2JjODMwOGFkNmJkYTdjYWRjZS5zZXRDb250ZW50KGh0bWxfMmFiMGUxZGQ2NjA4NDUzOTlmZDNmZGJkMGVkNGU1ZTApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOGE4MGIxODhhMjBlNDM1MjllOTE2NWI1NzVlMjljMDEuYmluZFBvcHVwKHBvcHVwXzdiOTA3ODA0NTgxMDQzYmM4MzA4YWQ2YmRhN2NhZGNlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2UyODhiMTI5M2JjNjQ4MTFhYzg3Y2IxODEwYjVlZjU3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzU2MzAzMywtNzkuNTY1OTYzMjk5OTk5OTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZDlhZTg2MjE1MWRlNDU2YjkzYTI1Mjc2NDQ1OGE4NzggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYTM1YzEwNTZmMTBjNGM5OWJiN2NhY2UxMTFjMDdmZTQgPSAkKCc8ZGl2IGlkPSJodG1sX2EzNWMxMDU2ZjEwYzRjOTliYjdjYWNlMTExYzA3ZmU0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IdW1iZXIgU3VtbWl0LCBOb3J0aCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9kOWFlODYyMTUxZGU0NTZiOTNhMjUyNzY0NDU4YTg3OC5zZXRDb250ZW50KGh0bWxfYTM1YzEwNTZmMTBjNGM5OWJiN2NhY2UxMTFjMDdmZTQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZTI4OGIxMjkzYmM2NDgxMWFjODdjYjE4MTBiNWVmNTcuYmluZFBvcHVwKHBvcHVwX2Q5YWU4NjIxNTFkZTQ1NmI5M2EyNTI3NjQ0NThhODc4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2IyMjBhYzVlNmIwYzQ3Y2E5MTJmMTVmZTEyZWIzMGM3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzI0NzY1OSwtNzkuNTMyMjQyNDAwMDAwMDJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNGU1ZWQ5MTViYmZmNDNiYjk2OWZjMDE0YjUxZTI0NjAgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZDUwOGExYzBkMTExNDY3NGEwN2NhMzhhMGZiNjEzMWEgPSAkKCc8ZGl2IGlkPSJodG1sX2Q1MDhhMWMwZDExMTQ2NzRhMDdjYTM4YTBmYjYxMzFhIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FbWVyeSwgSHVtYmVybGVhLCBOb3J0aCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80ZTVlZDkxNWJiZmY0M2JiOTY5ZmMwMTRiNTFlMjQ2MC5zZXRDb250ZW50KGh0bWxfZDUwOGExYzBkMTExNDY3NGEwN2NhMzhhMGZiNjEzMWEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYjIyMGFjNWU2YjBjNDdjYTkxMmYxNWZlMTJlYjMwYzcuYmluZFBvcHVwKHBvcHVwXzRlNWVkOTE1YmJmZjQzYmI5NjlmYzAxNGI1MWUyNDYwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzkzZTRkN2YyMDE5NzQzNDViOWNmNjhmYmIyMDM3ZmMzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzA2ODc2LC03OS41MTgxODg0MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF84MDVmMWI3ZDg4NDc0MjQxYmFjY2NkOGZkMzI1M2IyNCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81ZGIxY2Q4YzBhMzU0YmZkYjQ1OGQ4ZTQ2NzJmNjc3MSA9ICQoJzxkaXYgaWQ9Imh0bWxfNWRiMWNkOGMwYTM1NGJmZGI0NThkOGU0NjcyZjY3NzEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldlc3RvbiwgWW9yazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfODA1ZjFiN2Q4ODQ3NDI0MWJhY2NjZDhmZDMyNTNiMjQuc2V0Q29udGVudChodG1sXzVkYjFjZDhjMGEzNTRiZmRiNDU4ZDhlNDY3MmY2NzcxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzkzZTRkN2YyMDE5NzQzNDViOWNmNjhmYmIyMDM3ZmMzLmJpbmRQb3B1cChwb3B1cF84MDVmMWI3ZDg4NDc0MjQxYmFjY2NkOGZkMzI1M2IyNCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84NjQ0MmQ4NTg5NGM0ZjkwODg4NzM4YzJlOTMzODNiMiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY5NjMxOSwtNzkuNTMyMjQyNDAwMDAwMDJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfNDU1ODA0OWY0Y2IwNDQzOWI0MTk5Y2I1ZjUxNjc0MGIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYTllM2UxZGU0Mjc3NGI4YWIyM2M5YTFlMWY2YzgyYTMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfY2EwNzk1NzUwYTBlNDY1Yzg3MmVkMDM3MzEyYWQyYjIgPSAkKCc8ZGl2IGlkPSJodG1sX2NhMDc5NTc1MGEwZTQ2NWM4NzJlZDAzNzMxMmFkMmIyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5XZXN0bW91bnQsIEV0b2JpY29rZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYTllM2UxZGU0Mjc3NGI4YWIyM2M5YTFlMWY2YzgyYTMuc2V0Q29udGVudChodG1sX2NhMDc5NTc1MGEwZTQ2NWM4NzJlZDAzNzMxMmFkMmIyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzg2NDQyZDg1ODk0YzRmOTA4ODg3MzhjMmU5MzM4M2IyLmJpbmRQb3B1cChwb3B1cF9hOWUzZTFkZTQyNzc0YjhhYjIzYzlhMWUxZjZjODJhMyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hZjI2MDNkYzdmYzY0N2M4YjNlMzVkM2Y5ZTcxOTkwNyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY4ODkwNTQsLTc5LjU1NDcyNDQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzQ1NTgwNDlmNGNiMDQ0MzliNDE5OWNiNWY1MTY3NDBiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2ZmODM0NGM3ZmY0ZTQ5M2I4ZTMxMjZiZDFmZTdjOTdhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzdmMDdmOGQ4YTU2ZTQ0ZmRiOTY2MzMzZjk0Y2EzODQ3ID0gJCgnPGRpdiBpZD0iaHRtbF83ZjA3ZjhkOGE1NmU0NGZkYjk2NjMzM2Y5NGNhMzg0NyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+S2luZ3N2aWV3IFZpbGxhZ2UsIE1hcnRpbiBHcm92ZSBHYXJkZW5zLCBSaWNodmlldyBHYXJkZW5zLCBTdC4gUGhpbGxpcHMsIEV0b2JpY29rZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZmY4MzQ0YzdmZjRlNDkzYjhlMzEyNmJkMWZlN2M5N2Euc2V0Q29udGVudChodG1sXzdmMDdmOGQ4YTU2ZTQ0ZmRiOTY2MzMzZjk0Y2EzODQ3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2FmMjYwM2RjN2ZjNjQ3YzhiM2UzNWQzZjllNzE5OTA3LmJpbmRQb3B1cChwb3B1cF9mZjgzNDRjN2ZmNGU0OTNiOGUzMTI2YmQxZmU3Yzk3YSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9lNmExYmE5ZGI4ODA0MDk1YWEyMmJjZmQ5NjA5YjMyZSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjczOTQxNjM5OTk5OTk5NiwtNzkuNTg4NDM2OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jYjIyYTBhNGM1YjE0NTFhODYzNzdiNDg0MGViMTM4NSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9hMjk2YzBkOWFmMmE0ZTZkYjc1Y2VjYTNlYWZmYjQxZSA9ICQoJzxkaXYgaWQ9Imh0bWxfYTI5NmMwZDlhZjJhNGU2ZGI3NWNlY2EzZWFmZmI0MWUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkFsYmlvbiBHYXJkZW5zLCBCZWF1bW9uZCBIZWlnaHRzLCBIdW1iZXJnYXRlLCBKYW1lc3Rvd24sIE1vdW50IE9saXZlLCBTaWx2ZXJzdG9uZSwgU291dGggU3RlZWxlcywgVGhpc3RsZXRvd24sIEV0b2JpY29rZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfY2IyMmEwYTRjNWIxNDUxYTg2Mzc3YjQ4NDBlYjEzODUuc2V0Q29udGVudChodG1sX2EyOTZjMGQ5YWYyYTRlNmRiNzVjZWNhM2VhZmZiNDFlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2U2YTFiYTlkYjg4MDQwOTVhYTIyYmNmZDk2MDliMzJlLmJpbmRQb3B1cChwb3B1cF9jYjIyYTBhNGM1YjE0NTFhODYzNzdiNDg0MGViMTM4NSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mMDllMTczZGJiY2I0OGRjYjExMjYyYjk1MDVhMjI0MiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcwNjc0ODI5OTk5OTk5NCwtNzkuNTk0MDU0NF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF80NTU4MDQ5ZjRjYjA0NDM5YjQxOTljYjVmNTE2NzQwYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wODFkMmE0ODI0NWY0ZWJiOTI3OTlhN2IyMmQyN2UxMiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mZGRhN2U0NjM0MGQ0MjRjYjg1NzZmMmY1ZTYyNTk1OSA9ICQoJzxkaXYgaWQ9Imh0bWxfZmRkYTdlNDYzNDBkNDI0Y2I4NTc2ZjJmNWU2MjU5NTkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5vcnRod2VzdCwgRXRvYmljb2tlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8wODFkMmE0ODI0NWY0ZWJiOTI3OTlhN2IyMmQyN2UxMi5zZXRDb250ZW50KGh0bWxfZmRkYTdlNDYzNDBkNDI0Y2I4NTc2ZjJmNWU2MjU5NTkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZjA5ZTE3M2RiYmNiNDhkY2IxMTI2MmI5NTA1YTIyNDIuYmluZFBvcHVwKHBvcHVwXzA4MWQyYTQ4MjQ1ZjRlYmI5Mjc5OWE3YjIyZDI3ZTEyKTsKCiAgICAgICAgICAgIAogICAgICAgIAo8L3NjcmlwdD4=\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
      ],
      "text/plain": [
       "<folium.folium.Map at 0x1a1ae0b4a8>"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# create map of Toronto\n",
    "map_toronto = folium.Map(location=[latitude, longitude], zoom_start=10)\n",
    "\n",
    "# add markers to map\n",
    "for lat, lng, borough, neighborhood in zip(toronto_data['Latitude'], toronto_data['Longitude'], toronto_data['Borough'], toronto_data['Neighborhood']):\n",
    "    label = '{}, {}'.format(neighborhood, borough)\n",
    "    label = folium.Popup(label, parse_html=True)\n",
    "    folium.CircleMarker(\n",
    "        [lat, lng],\n",
    "        radius=5,\n",
    "        popup=label,\n",
    "        color='blue',\n",
    "        fill=True,\n",
    "        fill_color='#3186cc',\n",
    "        fill_opacity=0.7,\n",
    "        parse_html=False).add_to(map_toronto)  \n",
    "    \n",
    "map_toronto"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['Scarborough', 'North York', 'East York', 'East Toronto',\n",
       "       'Central Toronto', 'Downtown Toronto', 'York', 'West Toronto',\n",
       "       \"Queen's Park\", 'Mississauga', 'Etobicoke'], dtype=object)"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# get unique Borough\n",
    "toronto_data['Borough'].unique()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Postalcode</th>\n",
       "      <th>Borough</th>\n",
       "      <th>Neighborhood</th>\n",
       "      <th>Latitude</th>\n",
       "      <th>Longitude</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>M4E</td>\n",
       "      <td>East Toronto</td>\n",
       "      <td>The Beaches</td>\n",
       "      <td>43.6764</td>\n",
       "      <td>-79.293</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>M4K</td>\n",
       "      <td>East Toronto</td>\n",
       "      <td>The Danforth West, Riverdale</td>\n",
       "      <td>43.6796</td>\n",
       "      <td>-79.3522</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>M4L</td>\n",
       "      <td>East Toronto</td>\n",
       "      <td>The Beaches West, India Bazaar</td>\n",
       "      <td>43.669</td>\n",
       "      <td>-79.3156</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>M4M</td>\n",
       "      <td>East Toronto</td>\n",
       "      <td>Studio District</td>\n",
       "      <td>43.6595</td>\n",
       "      <td>-79.3409</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>M7Y</td>\n",
       "      <td>East Toronto</td>\n",
       "      <td>Business Reply Mail Processing Centre 969 Eastern</td>\n",
       "      <td>43.6627</td>\n",
       "      <td>-79.3216</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>M4N</td>\n",
       "      <td>Central Toronto</td>\n",
       "      <td>Lawrence Park</td>\n",
       "      <td>43.728</td>\n",
       "      <td>-79.3888</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>M4P</td>\n",
       "      <td>Central Toronto</td>\n",
       "      <td>Davisville North</td>\n",
       "      <td>43.7128</td>\n",
       "      <td>-79.3902</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>M4R</td>\n",
       "      <td>Central Toronto</td>\n",
       "      <td>North Toronto West</td>\n",
       "      <td>43.7154</td>\n",
       "      <td>-79.4057</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>M4S</td>\n",
       "      <td>Central Toronto</td>\n",
       "      <td>Davisville</td>\n",
       "      <td>43.7043</td>\n",
       "      <td>-79.3888</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>M4T</td>\n",
       "      <td>Central Toronto</td>\n",
       "      <td>Moore Park, Summerhill East</td>\n",
       "      <td>43.6896</td>\n",
       "      <td>-79.3832</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>M4V</td>\n",
       "      <td>Central Toronto</td>\n",
       "      <td>Deer Park, Forest Hill SE, Rathnelly, South Hi...</td>\n",
       "      <td>43.6864</td>\n",
       "      <td>-79.4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>M5N</td>\n",
       "      <td>Central Toronto</td>\n",
       "      <td>Roselawn</td>\n",
       "      <td>43.7117</td>\n",
       "      <td>-79.4169</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>M5P</td>\n",
       "      <td>Central Toronto</td>\n",
       "      <td>Forest Hill North, Forest Hill West</td>\n",
       "      <td>43.6969</td>\n",
       "      <td>-79.4113</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>M5R</td>\n",
       "      <td>Central Toronto</td>\n",
       "      <td>The Annex, North Midtown, Yorkville</td>\n",
       "      <td>43.6727</td>\n",
       "      <td>-79.4057</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>M4W</td>\n",
       "      <td>Downtown Toronto</td>\n",
       "      <td>Rosedale</td>\n",
       "      <td>43.6796</td>\n",
       "      <td>-79.3775</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>M4X</td>\n",
       "      <td>Downtown Toronto</td>\n",
       "      <td>Cabbagetown, St. James Town</td>\n",
       "      <td>43.668</td>\n",
       "      <td>-79.3677</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>M4Y</td>\n",
       "      <td>Downtown Toronto</td>\n",
       "      <td>Church and Wellesley</td>\n",
       "      <td>43.6659</td>\n",
       "      <td>-79.3832</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>M5A</td>\n",
       "      <td>Downtown Toronto</td>\n",
       "      <td>Harbourfront</td>\n",
       "      <td>43.6543</td>\n",
       "      <td>-79.3606</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>M5B</td>\n",
       "      <td>Downtown Toronto</td>\n",
       "      <td>Ryerson, Garden District</td>\n",
       "      <td>43.6572</td>\n",
       "      <td>-79.3789</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>M5C</td>\n",
       "      <td>Downtown Toronto</td>\n",
       "      <td>St. James Town</td>\n",
       "      <td>43.6515</td>\n",
       "      <td>-79.3754</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20</th>\n",
       "      <td>M5E</td>\n",
       "      <td>Downtown Toronto</td>\n",
       "      <td>Berczy Park</td>\n",
       "      <td>43.6448</td>\n",
       "      <td>-79.3733</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>21</th>\n",
       "      <td>M5G</td>\n",
       "      <td>Downtown Toronto</td>\n",
       "      <td>Central Bay Street</td>\n",
       "      <td>43.658</td>\n",
       "      <td>-79.3874</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>22</th>\n",
       "      <td>M5H</td>\n",
       "      <td>Downtown Toronto</td>\n",
       "      <td>Adelaide, King, Richmond</td>\n",
       "      <td>43.6506</td>\n",
       "      <td>-79.3846</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>23</th>\n",
       "      <td>M5J</td>\n",
       "      <td>Downtown Toronto</td>\n",
       "      <td>Harbourfront East, Toronto Islands, Union Station</td>\n",
       "      <td>43.6408</td>\n",
       "      <td>-79.3818</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>24</th>\n",
       "      <td>M5K</td>\n",
       "      <td>Downtown Toronto</td>\n",
       "      <td>Design Exchange, Toronto Dominion Centre</td>\n",
       "      <td>43.6472</td>\n",
       "      <td>-79.3816</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25</th>\n",
       "      <td>M5L</td>\n",
       "      <td>Downtown Toronto</td>\n",
       "      <td>Commerce Court, Victoria Hotel</td>\n",
       "      <td>43.6482</td>\n",
       "      <td>-79.3798</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>26</th>\n",
       "      <td>M5S</td>\n",
       "      <td>Downtown Toronto</td>\n",
       "      <td>Harbord, University of Toronto</td>\n",
       "      <td>43.6627</td>\n",
       "      <td>-79.4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>27</th>\n",
       "      <td>M5T</td>\n",
       "      <td>Downtown Toronto</td>\n",
       "      <td>Chinatown, Grange Park, Kensington Market</td>\n",
       "      <td>43.6532</td>\n",
       "      <td>-79.4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>28</th>\n",
       "      <td>M5V</td>\n",
       "      <td>Downtown Toronto</td>\n",
       "      <td>CN Tower, Bathurst Quay, Island airport, Harbo...</td>\n",
       "      <td>43.6289</td>\n",
       "      <td>-79.3944</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>29</th>\n",
       "      <td>M5W</td>\n",
       "      <td>Downtown Toronto</td>\n",
       "      <td>Stn A PO Boxes 25 The Esplanade</td>\n",
       "      <td>43.6464</td>\n",
       "      <td>-79.3748</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>30</th>\n",
       "      <td>M5X</td>\n",
       "      <td>Downtown Toronto</td>\n",
       "      <td>First Canadian Place, Underground city</td>\n",
       "      <td>43.6484</td>\n",
       "      <td>-79.3823</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>31</th>\n",
       "      <td>M6G</td>\n",
       "      <td>Downtown Toronto</td>\n",
       "      <td>Christie</td>\n",
       "      <td>43.6695</td>\n",
       "      <td>-79.4226</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>32</th>\n",
       "      <td>M9A</td>\n",
       "      <td>Downtown Toronto</td>\n",
       "      <td>Queen's Park</td>\n",
       "      <td>43.6679</td>\n",
       "      <td>-79.5322</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>33</th>\n",
       "      <td>M6H</td>\n",
       "      <td>West Toronto</td>\n",
       "      <td>Dovercourt Village, Dufferin</td>\n",
       "      <td>43.669</td>\n",
       "      <td>-79.4423</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>34</th>\n",
       "      <td>M6J</td>\n",
       "      <td>West Toronto</td>\n",
       "      <td>Little Portugal, Trinity</td>\n",
       "      <td>43.6479</td>\n",
       "      <td>-79.4197</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>35</th>\n",
       "      <td>M6K</td>\n",
       "      <td>West Toronto</td>\n",
       "      <td>Brockton, Exhibition Place, Parkdale Village</td>\n",
       "      <td>43.6368</td>\n",
       "      <td>-79.4282</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>36</th>\n",
       "      <td>M6P</td>\n",
       "      <td>West Toronto</td>\n",
       "      <td>High Park, The Junction South</td>\n",
       "      <td>43.6616</td>\n",
       "      <td>-79.4648</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>37</th>\n",
       "      <td>M6R</td>\n",
       "      <td>West Toronto</td>\n",
       "      <td>Parkdale, Roncesvalles</td>\n",
       "      <td>43.649</td>\n",
       "      <td>-79.4563</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>38</th>\n",
       "      <td>M6S</td>\n",
       "      <td>West Toronto</td>\n",
       "      <td>Runnymede, Swansea</td>\n",
       "      <td>43.6516</td>\n",
       "      <td>-79.4844</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   Postalcode           Borough  \\\n",
       "0         M4E      East Toronto   \n",
       "1         M4K      East Toronto   \n",
       "2         M4L      East Toronto   \n",
       "3         M4M      East Toronto   \n",
       "4         M7Y      East Toronto   \n",
       "5         M4N   Central Toronto   \n",
       "6         M4P   Central Toronto   \n",
       "7         M4R   Central Toronto   \n",
       "8         M4S   Central Toronto   \n",
       "9         M4T   Central Toronto   \n",
       "10        M4V   Central Toronto   \n",
       "11        M5N   Central Toronto   \n",
       "12        M5P   Central Toronto   \n",
       "13        M5R   Central Toronto   \n",
       "14        M4W  Downtown Toronto   \n",
       "15        M4X  Downtown Toronto   \n",
       "16        M4Y  Downtown Toronto   \n",
       "17        M5A  Downtown Toronto   \n",
       "18        M5B  Downtown Toronto   \n",
       "19        M5C  Downtown Toronto   \n",
       "20        M5E  Downtown Toronto   \n",
       "21        M5G  Downtown Toronto   \n",
       "22        M5H  Downtown Toronto   \n",
       "23        M5J  Downtown Toronto   \n",
       "24        M5K  Downtown Toronto   \n",
       "25        M5L  Downtown Toronto   \n",
       "26        M5S  Downtown Toronto   \n",
       "27        M5T  Downtown Toronto   \n",
       "28        M5V  Downtown Toronto   \n",
       "29        M5W  Downtown Toronto   \n",
       "30        M5X  Downtown Toronto   \n",
       "31        M6G  Downtown Toronto   \n",
       "32        M9A  Downtown Toronto   \n",
       "33        M6H      West Toronto   \n",
       "34        M6J      West Toronto   \n",
       "35        M6K      West Toronto   \n",
       "36        M6P      West Toronto   \n",
       "37        M6R      West Toronto   \n",
       "38        M6S      West Toronto   \n",
       "\n",
       "                                         Neighborhood Latitude Longitude  \n",
       "0                                         The Beaches  43.6764   -79.293  \n",
       "1                        The Danforth West, Riverdale  43.6796  -79.3522  \n",
       "2                      The Beaches West, India Bazaar   43.669  -79.3156  \n",
       "3                                     Studio District  43.6595  -79.3409  \n",
       "4   Business Reply Mail Processing Centre 969 Eastern  43.6627  -79.3216  \n",
       "5                                       Lawrence Park   43.728  -79.3888  \n",
       "6                                    Davisville North  43.7128  -79.3902  \n",
       "7                                  North Toronto West  43.7154  -79.4057  \n",
       "8                                          Davisville  43.7043  -79.3888  \n",
       "9                         Moore Park, Summerhill East  43.6896  -79.3832  \n",
       "10  Deer Park, Forest Hill SE, Rathnelly, South Hi...  43.6864     -79.4  \n",
       "11                                           Roselawn  43.7117  -79.4169  \n",
       "12                Forest Hill North, Forest Hill West  43.6969  -79.4113  \n",
       "13                The Annex, North Midtown, Yorkville  43.6727  -79.4057  \n",
       "14                                           Rosedale  43.6796  -79.3775  \n",
       "15                        Cabbagetown, St. James Town   43.668  -79.3677  \n",
       "16                               Church and Wellesley  43.6659  -79.3832  \n",
       "17                                       Harbourfront  43.6543  -79.3606  \n",
       "18                           Ryerson, Garden District  43.6572  -79.3789  \n",
       "19                                     St. James Town  43.6515  -79.3754  \n",
       "20                                        Berczy Park  43.6448  -79.3733  \n",
       "21                                 Central Bay Street   43.658  -79.3874  \n",
       "22                           Adelaide, King, Richmond  43.6506  -79.3846  \n",
       "23  Harbourfront East, Toronto Islands, Union Station  43.6408  -79.3818  \n",
       "24           Design Exchange, Toronto Dominion Centre  43.6472  -79.3816  \n",
       "25                     Commerce Court, Victoria Hotel  43.6482  -79.3798  \n",
       "26                     Harbord, University of Toronto  43.6627     -79.4  \n",
       "27          Chinatown, Grange Park, Kensington Market  43.6532     -79.4  \n",
       "28  CN Tower, Bathurst Quay, Island airport, Harbo...  43.6289  -79.3944  \n",
       "29                    Stn A PO Boxes 25 The Esplanade  43.6464  -79.3748  \n",
       "30             First Canadian Place, Underground city  43.6484  -79.3823  \n",
       "31                                           Christie  43.6695  -79.4226  \n",
       "32                                       Queen's Park  43.6679  -79.5322  \n",
       "33                       Dovercourt Village, Dufferin   43.669  -79.4423  \n",
       "34                           Little Portugal, Trinity  43.6479  -79.4197  \n",
       "35       Brockton, Exhibition Place, Parkdale Village  43.6368  -79.4282  \n",
       "36                      High Park, The Junction South  43.6616  -79.4648  \n",
       "37                             Parkdale, Roncesvalles   43.649  -79.4563  \n",
       "38                                 Runnymede, Swansea  43.6516  -79.4844  "
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# we only analyze the Borough contain the word Toronto\n",
    "import numpy as np\n",
    "toronto_dataE = toronto_data[toronto_data['Borough'] == 'East Toronto'].reset_index(drop=True)\n",
    "toronto_dataC = toronto_data[toronto_data['Borough'] == 'Central Toronto'].reset_index(drop=True)\n",
    "toronto_dataD = toronto_data[toronto_data['Borough'] == 'Downtown Toronto'].reset_index(drop=True)\n",
    "toronto_dataW = toronto_data[toronto_data['Borough'] == 'West Toronto'].reset_index(drop=True)\n",
    "toronto_data2 = np.vstack((toronto_dataE,toronto_dataC,toronto_dataD,toronto_dataW))\n",
    "toronto_data2 = pd.DataFrame(toronto_data2)\n",
    "toronto_data2.rename(columns={0:'Postalcode',1:'Borough',2:'Neighborhood',3:'Latitude',4:'Longitude'}, inplace=True)\n",
    "toronto_data2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Your credentails:\n",
      "CLIENT_ID: TD0N5N3O0P1FEQG1FNZE0PMXULS5RKOAKEVVBBS0PEEHZREA\n",
      "CLIENT_SECRET:YP5N1KZAPRGUONVFE3ZMMBASURZ1UP2AO02G1UNXJ1S15ZBI\n"
     ]
    }
   ],
   "source": [
    "CLIENT_ID = 'TD0N5N3O0P1FEQG1FNZE0PMXULS5RKOAKEVVBBS0PEEHZREA' # your Foursquare ID\n",
    "CLIENT_SECRET = 'YP5N1KZAPRGUONVFE3ZMMBASURZ1UP2AO02G1UNXJ1S15ZBI' # your Foursquare Secret\n",
    "VERSION = '20180605' # Foursquare API version\n",
    "\n",
    "print('Your credentails:')\n",
    "print('CLIENT_ID: ' + CLIENT_ID)\n",
    "print('CLIENT_SECRET:' + CLIENT_SECRET)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'The Beaches'"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#examine the first neiborhood\n",
    "toronto_data2.loc[0, 'Neighborhood']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Latitude and longitude values of The Beaches are 43.67635739999999, -79.2930312.\n"
     ]
    }
   ],
   "source": [
    "#get its geo data\n",
    "neighborhood_latitude = toronto_data2.loc[0, 'Latitude'] # neighborhood latitude value\n",
    "neighborhood_longitude = toronto_data2.loc[0, 'Longitude'] # neighborhood longitude value\n",
    "\n",
    "neighborhood_name = toronto_data2.loc[0, 'Neighborhood'] # neighborhood name\n",
    "\n",
    "print('Latitude and longitude values of {} are {}, {}.'.format(neighborhood_name, \n",
    "                                                               neighborhood_latitude, \n",
    "                                                               neighborhood_longitude))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Get the top 100 venues in Rouge and Malvern\n",
    "LIMIT = 100 \n",
    "radius = 500 \n",
    "url = 'https://api.foursquare.com/v2/venues/explore?&client_id={}&client_secret={}&v={}&ll={},{}&radius={}&limit={}'.format(\n",
    "    CLIENT_ID, \n",
    "    CLIENT_SECRET, \n",
    "    VERSION, \n",
    "    neighborhood_latitude, \n",
    "    neighborhood_longitude, \n",
    "    radius, \n",
    "    LIMIT)\n",
    "results = requests.get(url).json()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [],
   "source": [
    "# function that extracts the category of the venue\n",
    "def get_category_type(row):\n",
    "    try:\n",
    "        categories_list = row['categories']\n",
    "    except:\n",
    "        categories_list = row['venue.categories']\n",
    "        \n",
    "    if len(categories_list) == 0:\n",
    "        return None\n",
    "    else:\n",
    "        return categories_list[0]['name']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>name</th>\n",
       "      <th>categories</th>\n",
       "      <th>lat</th>\n",
       "      <th>lng</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Glen Manor Ravine</td>\n",
       "      <td>Trail</td>\n",
       "      <td>43.676821</td>\n",
       "      <td>-79.293942</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>The Big Carrot Natural Food Market</td>\n",
       "      <td>Health Food Store</td>\n",
       "      <td>43.678879</td>\n",
       "      <td>-79.297734</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Grover Pub and Grub</td>\n",
       "      <td>Pub</td>\n",
       "      <td>43.679181</td>\n",
       "      <td>-79.297215</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Domino's Pizza</td>\n",
       "      <td>Pizza Place</td>\n",
       "      <td>43.679058</td>\n",
       "      <td>-79.297382</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Upper Beaches</td>\n",
       "      <td>Neighborhood</td>\n",
       "      <td>43.680563</td>\n",
       "      <td>-79.292869</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                 name         categories        lat        lng\n",
       "0                   Glen Manor Ravine              Trail  43.676821 -79.293942\n",
       "1  The Big Carrot Natural Food Market  Health Food Store  43.678879 -79.297734\n",
       "2                 Grover Pub and Grub                Pub  43.679181 -79.297215\n",
       "3                      Domino's Pizza        Pizza Place  43.679058 -79.297382\n",
       "4                       Upper Beaches       Neighborhood  43.680563 -79.292869"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#\n",
    "venues = results['response']['groups'][0]['items']\n",
    "    \n",
    "nearby_venues = json_normalize(venues) # flatten JSON\n",
    "\n",
    "# filter columns\n",
    "filtered_columns = ['venue.name', 'venue.categories', 'venue.location.lat', 'venue.location.lng']\n",
    "nearby_venues =nearby_venues.loc[:, filtered_columns]\n",
    "\n",
    "# filter the category for each row\n",
    "nearby_venues['venue.categories'] = nearby_venues.apply(get_category_type, axis=1)\n",
    "\n",
    "# clean columns\n",
    "nearby_venues.columns = [col.split(\".\")[-1] for col in nearby_venues.columns]\n",
    "\n",
    "nearby_venues.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5 venues were returned by Foursquare.\n"
     ]
    }
   ],
   "source": [
    "print('{} venues were returned by Foursquare.'.format(nearby_venues.shape[0]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [],
   "source": [
    "#repeat the same process to all the neighborhoods in Toronto\n",
    "def getNearbyVenues(names, latitudes, longitudes, radius=500):\n",
    "    \n",
    "    venues_list=[]\n",
    "    for name, lat, lng in zip(names, latitudes, longitudes):\n",
    "        print(name)\n",
    "            \n",
    "        # create the API request URL\n",
    "        url = 'https://api.foursquare.com/v2/venues/explore?&client_id={}&client_secret={}&v={}&ll={},{}&radius={}&limit={}'.format(\n",
    "            CLIENT_ID, \n",
    "            CLIENT_SECRET, \n",
    "            VERSION, \n",
    "            lat, \n",
    "            lng, \n",
    "            radius, \n",
    "            LIMIT)\n",
    "            \n",
    "        # make the GET request\n",
    "        results = requests.get(url).json()[\"response\"]['groups'][0]['items']\n",
    "        \n",
    "        # return only relevant information for each nearby venue\n",
    "        venues_list.append([(\n",
    "            name, \n",
    "            lat, \n",
    "            lng, \n",
    "            v['venue']['name'], \n",
    "            v['venue']['location']['lat'], \n",
    "            v['venue']['location']['lng'],  \n",
    "            v['venue']['categories'][0]['name']) for v in results])\n",
    "\n",
    "    nearby_venues = pd.DataFrame([item for venue_list in venues_list for item in venue_list])\n",
    "    nearby_venues.columns = ['Neighborhood', \n",
    "                  'Neighborhood Latitude', \n",
    "                  'Neighborhood Longitude', \n",
    "                  'Venue', \n",
    "                  'Venue Latitude', \n",
    "                  'Venue Longitude', \n",
    "                  'Venue Category']\n",
    "    \n",
    "    return(nearby_venues)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The Beaches\n",
      "The Danforth West, Riverdale\n",
      "The Beaches West, India Bazaar\n",
      "Studio District\n",
      "Business Reply Mail Processing Centre 969 Eastern\n",
      "Lawrence Park\n",
      "Davisville North\n",
      "North Toronto West\n",
      "Davisville\n",
      "Moore Park, Summerhill East\n",
      "Deer Park, Forest Hill SE, Rathnelly, South Hill, Summerhill West\n",
      "Roselawn\n",
      "Forest Hill North, Forest Hill West\n",
      "The Annex, North Midtown, Yorkville\n",
      "Rosedale\n",
      "Cabbagetown, St. James Town\n",
      "Church and Wellesley\n",
      "Harbourfront\n",
      "Ryerson, Garden District\n",
      "St. James Town\n",
      "Berczy Park\n",
      "Central Bay Street\n",
      "Adelaide, King, Richmond\n",
      "Harbourfront East, Toronto Islands, Union Station\n",
      "Design Exchange, Toronto Dominion Centre\n",
      "Commerce Court, Victoria Hotel\n",
      "Harbord, University of Toronto\n",
      "Chinatown, Grange Park, Kensington Market\n",
      "CN Tower, Bathurst Quay, Island airport, Harbourfront West, King and Spadina, Railway Lands, South Niagara\n",
      "Stn A PO Boxes 25 The Esplanade\n",
      "First Canadian Place, Underground city\n",
      "Christie\n",
      "Queen's Park\n",
      "Dovercourt Village, Dufferin\n",
      "Little Portugal, Trinity\n",
      "Brockton, Exhibition Place, Parkdale Village\n",
      "High Park, The Junction South\n",
      "Parkdale, Roncesvalles\n",
      "Runnymede, Swansea\n"
     ]
    }
   ],
   "source": [
    "#get the name of toronto venues\n",
    "toronto_venues = getNearbyVenues(names=toronto_data2['Neighborhood'],\n",
    "                                   latitudes=toronto_data2['Latitude'],\n",
    "                                   longitudes=toronto_data2['Longitude']\n",
    "                                  )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "                                                   Neighborhood Latitude  \\\n",
      "Neighborhood                                                               \n",
      "Adelaide, King, Richmond                                             100   \n",
      "Berczy Park                                                           56   \n",
      "Brockton, Exhibition Place, Parkdale Village                          24   \n",
      "Business Reply Mail Processing Centre 969 Eastern                     17   \n",
      "\n",
      "                                                   Neighborhood Longitude  \\\n",
      "Neighborhood                                                                \n",
      "Adelaide, King, Richmond                                              100   \n",
      "Berczy Park                                                            56   \n",
      "Brockton, Exhibition Place, Parkdale Village                           24   \n",
      "Business Reply Mail Processing Centre 969 Eastern                      17   \n",
      "\n",
      "                                                   Venue  Venue Latitude  \\\n",
      "Neighborhood                                                               \n",
      "Adelaide, King, Richmond                             100             100   \n",
      "Berczy Park                                           56              56   \n",
      "Brockton, Exhibition Place, Parkdale Village          24              24   \n",
      "Business Reply Mail Processing Centre 969 Eastern     17              17   \n",
      "\n",
      "                                                   Venue Longitude  \\\n",
      "Neighborhood                                                         \n",
      "Adelaide, King, Richmond                                       100   \n",
      "Berczy Park                                                     56   \n",
      "Brockton, Exhibition Place, Parkdale Village                    24   \n",
      "Business Reply Mail Processing Centre 969 Eastern               17   \n",
      "\n",
      "                                                   Venue Category  \n",
      "Neighborhood                                                       \n",
      "Adelaide, King, Richmond                                      100  \n",
      "Berczy Park                                                    56  \n",
      "Brockton, Exhibition Place, Parkdale Village                   24  \n",
      "Business Reply Mail Processing Centre 969 Eastern              17  \n"
     ]
    }
   ],
   "source": [
    "toronto_venues.head(3)\n",
    "print(toronto_venues.groupby('Neighborhood').count()[:4])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {},
   "outputs": [],
   "source": [
    "# one hot encoding\n",
    "toronto_onehot = pd.get_dummies(toronto_venues[['Venue Category']], prefix=\"\", prefix_sep=\"\")\n",
    "\n",
    "# add neighborhood column back to dataframe\n",
    "toronto_onehot['Neighborhood'] = toronto_venues['Neighborhood'] \n",
    "\n",
    "# move neighborhood column to the first column\n",
    "fixed_columns = [toronto_onehot.columns[-1]] + list(toronto_onehot.columns[:-1])\n",
    "toronto_onehot = toronto_onehot[fixed_columns]\n",
    "\n",
    "toronto_grouped = toronto_onehot.groupby('Neighborhood').mean().reset_index()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Neighborhood</th>\n",
       "      <th>1st Most Common Venue</th>\n",
       "      <th>2nd Most Common Venue</th>\n",
       "      <th>3rd Most Common Venue</th>\n",
       "      <th>4th Most Common Venue</th>\n",
       "      <th>5th Most Common Venue</th>\n",
       "      <th>6th Most Common Venue</th>\n",
       "      <th>7th Most Common Venue</th>\n",
       "      <th>8th Most Common Venue</th>\n",
       "      <th>9th Most Common Venue</th>\n",
       "      <th>10th Most Common Venue</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Adelaide, King, Richmond</td>\n",
       "      <td>Coffee Shop</td>\n",
       "      <td>Café</td>\n",
       "      <td>Steakhouse</td>\n",
       "      <td>Bar</td>\n",
       "      <td>Salad Place</td>\n",
       "      <td>Bakery</td>\n",
       "      <td>Burger Joint</td>\n",
       "      <td>Restaurant</td>\n",
       "      <td>Thai Restaurant</td>\n",
       "      <td>Sushi Restaurant</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Berczy Park</td>\n",
       "      <td>Coffee Shop</td>\n",
       "      <td>Cocktail Bar</td>\n",
       "      <td>Café</td>\n",
       "      <td>Steakhouse</td>\n",
       "      <td>Farmers Market</td>\n",
       "      <td>Cheese Shop</td>\n",
       "      <td>Beer Bar</td>\n",
       "      <td>Bakery</td>\n",
       "      <td>Seafood Restaurant</td>\n",
       "      <td>Hotel</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Brockton, Exhibition Place, Parkdale Village</td>\n",
       "      <td>Café</td>\n",
       "      <td>Yoga Studio</td>\n",
       "      <td>Breakfast Spot</td>\n",
       "      <td>Coffee Shop</td>\n",
       "      <td>Gym</td>\n",
       "      <td>Pet Store</td>\n",
       "      <td>Performing Arts Venue</td>\n",
       "      <td>Music Venue</td>\n",
       "      <td>Italian Restaurant</td>\n",
       "      <td>Intersection</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Business Reply Mail Processing Centre 969 Eastern</td>\n",
       "      <td>Light Rail Station</td>\n",
       "      <td>Yoga Studio</td>\n",
       "      <td>Brewery</td>\n",
       "      <td>Burrito Place</td>\n",
       "      <td>Auto Workshop</td>\n",
       "      <td>Fast Food Restaurant</td>\n",
       "      <td>Farmers Market</td>\n",
       "      <td>Spa</td>\n",
       "      <td>Restaurant</td>\n",
       "      <td>Pizza Place</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>CN Tower, Bathurst Quay, Island airport, Harbo...</td>\n",
       "      <td>Airport Terminal</td>\n",
       "      <td>Airport Lounge</td>\n",
       "      <td>Boat or Ferry</td>\n",
       "      <td>Boutique</td>\n",
       "      <td>Rental Car Location</td>\n",
       "      <td>Plane</td>\n",
       "      <td>Coffee Shop</td>\n",
       "      <td>Harbor / Marina</td>\n",
       "      <td>Sculpture Garden</td>\n",
       "      <td>Airport Service</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                        Neighborhood 1st Most Common Venue  \\\n",
       "0                           Adelaide, King, Richmond           Coffee Shop   \n",
       "1                                        Berczy Park           Coffee Shop   \n",
       "2       Brockton, Exhibition Place, Parkdale Village                  Café   \n",
       "3  Business Reply Mail Processing Centre 969 Eastern    Light Rail Station   \n",
       "4  CN Tower, Bathurst Quay, Island airport, Harbo...      Airport Terminal   \n",
       "\n",
       "  2nd Most Common Venue 3rd Most Common Venue 4th Most Common Venue  \\\n",
       "0                  Café            Steakhouse                   Bar   \n",
       "1          Cocktail Bar                  Café            Steakhouse   \n",
       "2           Yoga Studio        Breakfast Spot           Coffee Shop   \n",
       "3           Yoga Studio               Brewery         Burrito Place   \n",
       "4        Airport Lounge         Boat or Ferry              Boutique   \n",
       "\n",
       "  5th Most Common Venue 6th Most Common Venue  7th Most Common Venue  \\\n",
       "0           Salad Place                Bakery           Burger Joint   \n",
       "1        Farmers Market           Cheese Shop               Beer Bar   \n",
       "2                   Gym             Pet Store  Performing Arts Venue   \n",
       "3         Auto Workshop  Fast Food Restaurant         Farmers Market   \n",
       "4   Rental Car Location                 Plane            Coffee Shop   \n",
       "\n",
       "  8th Most Common Venue 9th Most Common Venue 10th Most Common Venue  \n",
       "0            Restaurant       Thai Restaurant       Sushi Restaurant  \n",
       "1                Bakery    Seafood Restaurant                  Hotel  \n",
       "2           Music Venue    Italian Restaurant           Intersection  \n",
       "3                   Spa            Restaurant            Pizza Place  \n",
       "4       Harbor / Marina      Sculpture Garden        Airport Service  "
      ]
     },
     "execution_count": 90,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# define a function to get the most common venues\n",
    "def return_most_common_venues(row, num_top_venues):\n",
    "    row_categories = row.iloc[1:]\n",
    "    row_categories_sorted = row_categories.sort_values(ascending=False)\n",
    "    \n",
    "    return row_categories_sorted.index.values[0:num_top_venues]\n",
    "\n",
    "# get the 10 most common\n",
    "num_top_venues = 10\n",
    "\n",
    "indicators = ['st', 'nd', 'rd']\n",
    "\n",
    "# create columns according to number of top venues\n",
    "columns = ['Neighborhood']\n",
    "for ind in np.arange(num_top_venues):\n",
    "    try:\n",
    "        columns.append('{}{} Most Common Venue'.format(ind+1, indicators[ind]))\n",
    "    except:\n",
    "        columns.append('{}th Most Common Venue'.format(ind+1))\n",
    "\n",
    "# create a new dataframe\n",
    "neighborhoods_venues_sorted = pd.DataFrame(columns=columns)\n",
    "neighborhoods_venues_sorted['Neighborhood'] = toronto_grouped['Neighborhood']\n",
    "\n",
    "for ind in np.arange(toronto_grouped.shape[0]):\n",
    "    neighborhoods_venues_sorted.iloc[ind, 1:] = return_most_common_venues(toronto_grouped.iloc[ind, :], num_top_venues)\n",
    "neighborhoods_venues_sorted.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0], dtype=int32)"
      ]
     },
     "execution_count": 91,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# set number of clusters\n",
    "kclusters = 5\n",
    "\n",
    "toronto_grouped_clustering = toronto_grouped.drop('Neighborhood', 1)\n",
    "\n",
    "# run k-means clustering\n",
    "kmeans = KMeans(n_clusters=kclusters, random_state=0).fit(toronto_grouped_clustering)\n",
    "\n",
    "# check cluster labels generated for each row in the dataframe\n",
    "kmeans.labels_[0:10]\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Postalcode</th>\n",
       "      <th>Borough</th>\n",
       "      <th>Neighborhood</th>\n",
       "      <th>Latitude</th>\n",
       "      <th>Longitude</th>\n",
       "      <th>Cluster Labels</th>\n",
       "      <th>1st Most Common Venue</th>\n",
       "      <th>2nd Most Common Venue</th>\n",
       "      <th>3rd Most Common Venue</th>\n",
       "      <th>4th Most Common Venue</th>\n",
       "      <th>5th Most Common Venue</th>\n",
       "      <th>6th Most Common Venue</th>\n",
       "      <th>7th Most Common Venue</th>\n",
       "      <th>8th Most Common Venue</th>\n",
       "      <th>9th Most Common Venue</th>\n",
       "      <th>10th Most Common Venue</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>M4E</td>\n",
       "      <td>East Toronto</td>\n",
       "      <td>The Beaches</td>\n",
       "      <td>43.6764</td>\n",
       "      <td>-79.293</td>\n",
       "      <td>0.0</td>\n",
       "      <td>Health Food Store</td>\n",
       "      <td>Pizza Place</td>\n",
       "      <td>Pub</td>\n",
       "      <td>Trail</td>\n",
       "      <td>Discount Store</td>\n",
       "      <td>Department Store</td>\n",
       "      <td>Dessert Shop</td>\n",
       "      <td>Dim Sum Restaurant</td>\n",
       "      <td>Diner</td>\n",
       "      <td>Wings Joint</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>M4K</td>\n",
       "      <td>East Toronto</td>\n",
       "      <td>The Danforth West, Riverdale</td>\n",
       "      <td>43.6796</td>\n",
       "      <td>-79.3522</td>\n",
       "      <td>0.0</td>\n",
       "      <td>Greek Restaurant</td>\n",
       "      <td>Coffee Shop</td>\n",
       "      <td>Ice Cream Shop</td>\n",
       "      <td>Restaurant</td>\n",
       "      <td>Furniture / Home Store</td>\n",
       "      <td>Bookstore</td>\n",
       "      <td>Italian Restaurant</td>\n",
       "      <td>Pub</td>\n",
       "      <td>Pizza Place</td>\n",
       "      <td>Liquor Store</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>M4L</td>\n",
       "      <td>East Toronto</td>\n",
       "      <td>The Beaches West, India Bazaar</td>\n",
       "      <td>43.669</td>\n",
       "      <td>-79.3156</td>\n",
       "      <td>0.0</td>\n",
       "      <td>Sushi Restaurant</td>\n",
       "      <td>Liquor Store</td>\n",
       "      <td>Fish &amp; Chips Shop</td>\n",
       "      <td>Pub</td>\n",
       "      <td>Ice Cream Shop</td>\n",
       "      <td>Fast Food Restaurant</td>\n",
       "      <td>Burrito Place</td>\n",
       "      <td>Burger Joint</td>\n",
       "      <td>Italian Restaurant</td>\n",
       "      <td>Pizza Place</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>M4M</td>\n",
       "      <td>East Toronto</td>\n",
       "      <td>Studio District</td>\n",
       "      <td>43.6595</td>\n",
       "      <td>-79.3409</td>\n",
       "      <td>0.0</td>\n",
       "      <td>Café</td>\n",
       "      <td>Coffee Shop</td>\n",
       "      <td>Gastropub</td>\n",
       "      <td>Bakery</td>\n",
       "      <td>Italian Restaurant</td>\n",
       "      <td>American Restaurant</td>\n",
       "      <td>Yoga Studio</td>\n",
       "      <td>Comfort Food Restaurant</td>\n",
       "      <td>Sandwich Place</td>\n",
       "      <td>Brewery</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>M7Y</td>\n",
       "      <td>East Toronto</td>\n",
       "      <td>Business Reply Mail Processing Centre 969 Eastern</td>\n",
       "      <td>43.6627</td>\n",
       "      <td>-79.3216</td>\n",
       "      <td>0.0</td>\n",
       "      <td>Light Rail Station</td>\n",
       "      <td>Yoga Studio</td>\n",
       "      <td>Brewery</td>\n",
       "      <td>Burrito Place</td>\n",
       "      <td>Auto Workshop</td>\n",
       "      <td>Fast Food Restaurant</td>\n",
       "      <td>Farmers Market</td>\n",
       "      <td>Spa</td>\n",
       "      <td>Restaurant</td>\n",
       "      <td>Pizza Place</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  Postalcode       Borough                                       Neighborhood  \\\n",
       "0        M4E  East Toronto                                        The Beaches   \n",
       "1        M4K  East Toronto                       The Danforth West, Riverdale   \n",
       "2        M4L  East Toronto                     The Beaches West, India Bazaar   \n",
       "3        M4M  East Toronto                                    Studio District   \n",
       "4        M7Y  East Toronto  Business Reply Mail Processing Centre 969 Eastern   \n",
       "\n",
       "  Latitude Longitude  Cluster Labels 1st Most Common Venue  \\\n",
       "0  43.6764   -79.293             0.0     Health Food Store   \n",
       "1  43.6796  -79.3522             0.0      Greek Restaurant   \n",
       "2   43.669  -79.3156             0.0      Sushi Restaurant   \n",
       "3  43.6595  -79.3409             0.0                  Café   \n",
       "4  43.6627  -79.3216             0.0    Light Rail Station   \n",
       "\n",
       "  2nd Most Common Venue 3rd Most Common Venue 4th Most Common Venue  \\\n",
       "0           Pizza Place                   Pub                 Trail   \n",
       "1           Coffee Shop        Ice Cream Shop            Restaurant   \n",
       "2          Liquor Store     Fish & Chips Shop                   Pub   \n",
       "3           Coffee Shop             Gastropub                Bakery   \n",
       "4           Yoga Studio               Brewery         Burrito Place   \n",
       "\n",
       "    5th Most Common Venue 6th Most Common Venue 7th Most Common Venue  \\\n",
       "0          Discount Store      Department Store          Dessert Shop   \n",
       "1  Furniture / Home Store             Bookstore    Italian Restaurant   \n",
       "2          Ice Cream Shop  Fast Food Restaurant         Burrito Place   \n",
       "3      Italian Restaurant   American Restaurant           Yoga Studio   \n",
       "4           Auto Workshop  Fast Food Restaurant        Farmers Market   \n",
       "\n",
       "     8th Most Common Venue 9th Most Common Venue 10th Most Common Venue  \n",
       "0       Dim Sum Restaurant                 Diner            Wings Joint  \n",
       "1                      Pub           Pizza Place           Liquor Store  \n",
       "2             Burger Joint    Italian Restaurant            Pizza Place  \n",
       "3  Comfort Food Restaurant        Sandwich Place                Brewery  \n",
       "4                      Spa            Restaurant            Pizza Place  "
      ]
     },
     "execution_count": 92,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# add clustering labels\n",
    "neighborhoods_venues_sorted.insert(0, 'Cluster Labels', kmeans.labels_)\n",
    "\n",
    "toronto_merged = toronto_data2\n",
    "\n",
    "# merge toronto_grouped with toronto_data to add latitude/longitude for each neighborhood\n",
    "toronto_merged = toronto_merged.join(neighborhoods_venues_sorted.set_index('Neighborhood'), on='Neighborhood')\n",
    "\n",
    "# check the last columns!\n",
    "toronto_merged.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVMgPSBmYWxzZTsgTF9OT19UT1VDSCA9IGZhbHNlOyBMX0RJU0FCTEVfM0QgPSBmYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2FqYXguZ29vZ2xlYXBpcy5jb20vYWpheC9saWJzL2pxdWVyeS8xLjExLjEvanF1ZXJ5Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdnaXQuY29tL3B5dGhvbi12aXN1YWxpemF0aW9uL2ZvbGl1bS9tYXN0ZXIvZm9saXVtL3RlbXBsYXRlcy9sZWFmbGV0LmF3ZXNvbWUucm90YXRlLmNzcyIvPgogICAgPHN0eWxlPmh0bWwsIGJvZHkge3dpZHRoOiAxMDAlO2hlaWdodDogMTAwJTttYXJnaW46IDA7cGFkZGluZzogMDt9PC9zdHlsZT4KICAgIDxzdHlsZT4jbWFwIHtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtib3R0b206MDtyaWdodDowO2xlZnQ6MDt9PC9zdHlsZT4KICAgIAogICAgICAgICAgICA8c3R5bGU+ICNtYXBfZGYxNjdmZjFmMzRhNGQzYWIwZTIzNjViZWZlZTZhMmIgewogICAgICAgICAgICAgICAgcG9zaXRpb24gOiByZWxhdGl2ZTsKICAgICAgICAgICAgICAgIHdpZHRoIDogMTAwLjAlOwogICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgICAgICAgICAgdG9wOiAwLjAlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICA8L3N0eWxlPgogICAgICAgIAo8L2hlYWQ+Cjxib2R5PiAgICAKICAgIAogICAgICAgICAgICA8ZGl2IGNsYXNzPSJmb2xpdW0tbWFwIiBpZD0ibWFwX2RmMTY3ZmYxZjM0YTRkM2FiMGUyMzY1YmVmZWU2YTJiIiA+PC9kaXY+CiAgICAgICAgCjwvYm9keT4KPHNjcmlwdD4gICAgCiAgICAKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGJvdW5kcyA9IG51bGw7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgdmFyIG1hcF9kZjE2N2ZmMWYzNGE0ZDNhYjBlMjM2NWJlZmVlNmEyYiA9IEwubWFwKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ21hcF9kZjE2N2ZmMWYzNGE0ZDNhYjBlMjM2NWJlZmVlNmEyYicsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7Y2VudGVyOiBbNDMuNjUzOTYzLC03OS4zODcyMDddLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgem9vbTogMTEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhCb3VuZHM6IGJvdW5kcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxheWVyczogW10sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JsZENvcHlKdW1wOiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyczogTC5DUlMuRVBTRzM4NTcKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciB0aWxlX2xheWVyXzU1MzNlM2Y3ZTY5ZTQ0MGQ5MDhkZDA5MDE4NGY5YjQwID0gTC50aWxlTGF5ZXIoCiAgICAgICAgICAgICAgICAnaHR0cHM6Ly97c30udGlsZS5vcGVuc3RyZWV0bWFwLm9yZy97en0ve3h9L3t5fS5wbmcnLAogICAgICAgICAgICAgICAgewogICJhdHRyaWJ1dGlvbiI6IG51bGwsCiAgImRldGVjdFJldGluYSI6IGZhbHNlLAogICJtYXhab29tIjogMTgsCiAgIm1pblpvb20iOiAxLAogICJub1dyYXAiOiBmYWxzZSwKICAic3ViZG9tYWlucyI6ICJhYmMiCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2RmMTY3ZmYxZjM0YTRkM2FiMGUyMzY1YmVmZWU2YTJiKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9lOWQyNzE3MzY1ZDA0MWNlYjA1NzM4N2Y3OGVjMGYyNiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY3NjM1NzM5OTk5OTk5LC03OS4yOTMwMzEyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMzMzg4ZmYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzM4OGZmIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2RmMTY3ZmYxZjM0YTRkM2FiMGUyMzY1YmVmZWU2YTJiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2QzYzE0MmVlYTNhNjQ2NzA4MjMyNzkyM2U3YzI3MmQ2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzUzYjQ4ZTUxZDg1NDQ2Mzc5ZTkyNTJkMjk3NjJlNTU5ID0gJCgnPGRpdiBpZD0iaHRtbF81M2I0OGU1MWQ4NTQ0NjM3OWU5MjUyZDI5NzYyZTU1OSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VGhlIEJlYWNoZXMgQ2x1c3RlciAwLjA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2QzYzE0MmVlYTNhNjQ2NzA4MjMyNzkyM2U3YzI3MmQ2LnNldENvbnRlbnQoaHRtbF81M2I0OGU1MWQ4NTQ0NjM3OWU5MjUyZDI5NzYyZTU1OSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9lOWQyNzE3MzY1ZDA0MWNlYjA1NzM4N2Y3OGVjMGYyNi5iaW5kUG9wdXAocG9wdXBfZDNjMTQyZWVhM2E2NDY3MDgyMzI3OTIzZTdjMjcyZDYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfM2M0NTc4MTIyYmQyNGY3NDlhYTcyNmI0MDE4NjQyODUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42Nzk1NTcxLC03OS4zNTIxODhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzMzODhmZiIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMzg4ZmYiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZGYxNjdmZjFmMzRhNGQzYWIwZTIzNjViZWZlZTZhMmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMzRmZWZhM2FlZmM2NDlkNjlmMDg1NDZjZTcxNTUzYmIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMjM1MDM5ODFlYWE2NDIzZDljZTFiODRhMDM1ZTc3MGYgPSAkKCc8ZGl2IGlkPSJodG1sXzIzNTAzOTgxZWFhNjQyM2Q5Y2UxYjg0YTAzNWU3NzBmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5UaGUgRGFuZm9ydGggV2VzdCwgUml2ZXJkYWxlIENsdXN0ZXIgMC4wPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zNGZlZmEzYWVmYzY0OWQ2OWYwODU0NmNlNzE1NTNiYi5zZXRDb250ZW50KGh0bWxfMjM1MDM5ODFlYWE2NDIzZDljZTFiODRhMDM1ZTc3MGYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfM2M0NTc4MTIyYmQyNGY3NDlhYTcyNmI0MDE4NjQyODUuYmluZFBvcHVwKHBvcHVwXzM0ZmVmYTNhZWZjNjQ5ZDY5ZjA4NTQ2Y2U3MTU1M2JiKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzA1NjYzMzFiMmFiYjQwNjQ4ODdmYTQyMmQ4ZGViYzJiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjY4OTk4NSwtNzkuMzE1NTcxNTk5OTk5OThdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzMzODhmZiIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMzg4ZmYiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZGYxNjdmZjFmMzRhNGQzYWIwZTIzNjViZWZlZTZhMmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZTg1YmZhNTBjNzExNGY0M2E1OTc5Zjc4Yzk4NWYyM2YgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNzc1NmZiMTYyMzQwNGMyZDkzNmI3NTljYTM3MTUyZGQgPSAkKCc8ZGl2IGlkPSJodG1sXzc3NTZmYjE2MjM0MDRjMmQ5MzZiNzU5Y2EzNzE1MmRkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5UaGUgQmVhY2hlcyBXZXN0LCBJbmRpYSBCYXphYXIgQ2x1c3RlciAwLjA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2U4NWJmYTUwYzcxMTRmNDNhNTk3OWY3OGM5ODVmMjNmLnNldENvbnRlbnQoaHRtbF83NzU2ZmIxNjIzNDA0YzJkOTM2Yjc1OWNhMzcxNTJkZCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wNTY2MzMxYjJhYmI0MDY0ODg3ZmE0MjJkOGRlYmMyYi5iaW5kUG9wdXAocG9wdXBfZTg1YmZhNTBjNzExNGY0M2E1OTc5Zjc4Yzk4NWYyM2YpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNjQzZmRjZTVmNTU4NDdmMjk4MDNlNjcwNzgzYmYwNjMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NTk1MjU1LC03OS4zNDA5MjNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzMzODhmZiIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMzg4ZmYiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZGYxNjdmZjFmMzRhNGQzYWIwZTIzNjViZWZlZTZhMmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNmNjMWRiZGQ3YzgyNDcyZDkzOTZmY2JiYjFiODdiNGIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZTk5YmI0YTUyZGIzNDg0YmFmYmNmOGE4OWEyMjE1MjkgPSAkKCc8ZGl2IGlkPSJodG1sX2U5OWJiNGE1MmRiMzQ4NGJhZmJjZjhhODlhMjIxNTI5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TdHVkaW8gRGlzdHJpY3QgQ2x1c3RlciAwLjA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzZjYzFkYmRkN2M4MjQ3MmQ5Mzk2ZmNiYmIxYjg3YjRiLnNldENvbnRlbnQoaHRtbF9lOTliYjRhNTJkYjM0ODRiYWZiY2Y4YTg5YTIyMTUyOSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82NDNmZGNlNWY1NTg0N2YyOTgwM2U2NzA3ODNiZjA2My5iaW5kUG9wdXAocG9wdXBfNmNjMWRiZGQ3YzgyNDcyZDkzOTZmY2JiYjFiODdiNGIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYmEyZjZhODc0N2QzNDI4N2I5NDNiNTk2ZWI0NDc3YzAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NjI3NDM5LC03OS4zMjE1NThdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzMzODhmZiIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMzg4ZmYiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZGYxNjdmZjFmMzRhNGQzYWIwZTIzNjViZWZlZTZhMmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMDA2NGFlNDkxMmQ5NDIwYWI4NmVlY2I4MzgwMjBhMzIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNTZiODBhYWQwYjJiNDQ2ZGI2NzFlMTQ4MDdkNzk2Y2YgPSAkKCc8ZGl2IGlkPSJodG1sXzU2YjgwYWFkMGIyYjQ0NmRiNjcxZTE0ODA3ZDc5NmNmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5CdXNpbmVzcyBSZXBseSBNYWlsIFByb2Nlc3NpbmcgQ2VudHJlIDk2OSBFYXN0ZXJuIENsdXN0ZXIgMC4wPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8wMDY0YWU0OTEyZDk0MjBhYjg2ZWVjYjgzODAyMGEzMi5zZXRDb250ZW50KGh0bWxfNTZiODBhYWQwYjJiNDQ2ZGI2NzFlMTQ4MDdkNzk2Y2YpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYmEyZjZhODc0N2QzNDI4N2I5NDNiNTk2ZWI0NDc3YzAuYmluZFBvcHVwKHBvcHVwXzAwNjRhZTQ5MTJkOTQyMGFiODZlZWNiODM4MDIwYTMyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzM3OWE5NjBlZDYyNjQ3MmZiOGVkNTM5MWM4YjU5ZGQ3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzI4MDIwNSwtNzkuMzg4NzkwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMzM4OGZmIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMzODhmZiIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kZjE2N2ZmMWYzNGE0ZDNhYjBlMjM2NWJlZmVlNmEyYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wZDliNWZhMTdmZTM0OTE2OGNhOWE2MWFjMjEwYjk4NiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81MGE4MjMzNzg1MzI0NGUxOGUwODQ0MTkzOTRiMDU5OSA9ICQoJzxkaXYgaWQ9Imh0bWxfNTBhODIzMzc4NTMyNDRlMThlMDg0NDE5Mzk0YjA1OTkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkxhd3JlbmNlIFBhcmsgQ2x1c3RlciA0LjA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzBkOWI1ZmExN2ZlMzQ5MTY4Y2E5YTYxYWMyMTBiOTg2LnNldENvbnRlbnQoaHRtbF81MGE4MjMzNzg1MzI0NGUxOGUwODQ0MTkzOTRiMDU5OSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8zNzlhOTYwZWQ2MjY0NzJmYjhlZDUzOTFjOGI1OWRkNy5iaW5kUG9wdXAocG9wdXBfMGQ5YjVmYTE3ZmUzNDkxNjhjYTlhNjFhYzIxMGI5ODYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZDIxNmMyMWZmOTk4NDVmYTgwMWI5ZGZjNzViNTVjODUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MTI3NTExLC03OS4zOTAxOTc1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMzMzg4ZmYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzM4OGZmIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2RmMTY3ZmYxZjM0YTRkM2FiMGUyMzY1YmVmZWU2YTJiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzY5YzBkOWMyZWY2NTRiOTA4NTllYTEwOWUzYjliMjc0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzBmN2U2ZjIxZWI2YTQxZDRiNjViZGE3Y2M3ZGNjOTVlID0gJCgnPGRpdiBpZD0iaHRtbF8wZjdlNmYyMWViNmE0MWQ0YjY1YmRhN2NjN2RjYzk1ZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RGF2aXN2aWxsZSBOb3J0aCBDbHVzdGVyIDAuMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNjljMGQ5YzJlZjY1NGI5MDg1OWVhMTA5ZTNiOWIyNzQuc2V0Q29udGVudChodG1sXzBmN2U2ZjIxZWI2YTQxZDRiNjViZGE3Y2M3ZGNjOTVlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2QyMTZjMjFmZjk5ODQ1ZmE4MDFiOWRmYzc1YjU1Yzg1LmJpbmRQb3B1cChwb3B1cF82OWMwZDljMmVmNjU0YjkwODU5ZWExMDllM2I5YjI3NCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jYzViNTQ4M2ZkNzA0NzMyOWUyODg1NWE1Y2M2ZWJiZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcxNTM4MzQsLTc5LjQwNTY3ODQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMzMzg4ZmYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzM4OGZmIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2RmMTY3ZmYxZjM0YTRkM2FiMGUyMzY1YmVmZWU2YTJiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzM4OWUxYjRmMDE2YjQ4NzFhMDIzNjJmZGZjYzdlZGZlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzRkMTA2NWE3YmZmMjQxZmZhODZjYTk5Mjg3NmY0NTA0ID0gJCgnPGRpdiBpZD0iaHRtbF80ZDEwNjVhN2JmZjI0MWZmYTg2Y2E5OTI4NzZmNDUwNCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Tm9ydGggVG9yb250byBXZXN0IENsdXN0ZXIgMC4wPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zODllMWI0ZjAxNmI0ODcxYTAyMzYyZmRmY2M3ZWRmZS5zZXRDb250ZW50KGh0bWxfNGQxMDY1YTdiZmYyNDFmZmE4NmNhOTkyODc2ZjQ1MDQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfY2M1YjU0ODNmZDcwNDczMjllMjg4NTVhNWNjNmViYmQuYmluZFBvcHVwKHBvcHVwXzM4OWUxYjRmMDE2YjQ4NzFhMDIzNjJmZGZjYzdlZGZlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzE3NmU5ODkyNjJlYjQxZDViYWU3Y2I0NGY1NWY0Y2E0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzA0MzI0NCwtNzkuMzg4NzkwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMzM4OGZmIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMzODhmZiIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kZjE2N2ZmMWYzNGE0ZDNhYjBlMjM2NWJlZmVlNmEyYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81NWE5YTc3MGI0MjA0NmZjODJmMmYxOTljMzc3ZmQ0NyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xYTE4NTQ4MDRmNTM0MGY5YTk0MDhlNTkzYmU1Y2ZhMiA9ICQoJzxkaXYgaWQ9Imh0bWxfMWExODU0ODA0ZjUzNDBmOWE5NDA4ZTU5M2JlNWNmYTIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRhdmlzdmlsbGUgQ2x1c3RlciAwLjA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzU1YTlhNzcwYjQyMDQ2ZmM4MmYyZjE5OWMzNzdmZDQ3LnNldENvbnRlbnQoaHRtbF8xYTE4NTQ4MDRmNTM0MGY5YTk0MDhlNTkzYmU1Y2ZhMik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8xNzZlOTg5MjYyZWI0MWQ1YmFlN2NiNDRmNTVmNGNhNC5iaW5kUG9wdXAocG9wdXBfNTVhOWE3NzBiNDIwNDZmYzgyZjJmMTk5YzM3N2ZkNDcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNTVjMmQyMWZkYTdlNDgxNWJhOWI4NWVkMWQ5MjA0OTggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42ODk1NzQzLC03OS4zODMxNTk5MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMzM4OGZmIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMzODhmZiIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kZjE2N2ZmMWYzNGE0ZDNhYjBlMjM2NWJlZmVlNmEyYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yMzg2ZDhkMDZmNzA0MjRiOTQ1OWZmYWFkZjMyMGI0OSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jYTczYjVjZjA4ZTY0ZjI2ODU1MWZmNTViYWNlMzNjYiA9ICQoJzxkaXYgaWQ9Imh0bWxfY2E3M2I1Y2YwOGU2NGYyNjg1NTFmZjU1YmFjZTMzY2IiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk1vb3JlIFBhcmssIFN1bW1lcmhpbGwgRWFzdCBDbHVzdGVyIDEuMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMjM4NmQ4ZDA2ZjcwNDI0Yjk0NTlmZmFhZGYzMjBiNDkuc2V0Q29udGVudChodG1sX2NhNzNiNWNmMDhlNjRmMjY4NTUxZmY1NWJhY2UzM2NiKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzU1YzJkMjFmZGE3ZTQ4MTViYTliODVlZDFkOTIwNDk4LmJpbmRQb3B1cChwb3B1cF8yMzg2ZDhkMDZmNzA0MjRiOTQ1OWZmYWFkZjMyMGI0OSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8zYjM0Nzc0NDUwODg0YjY0YjMxMTk0ZWE5NmRlNDhjNiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY4NjQxMjI5OTk5OTk5LC03OS40MDAwNDkzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMzMzg4ZmYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzM4OGZmIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2RmMTY3ZmYxZjM0YTRkM2FiMGUyMzY1YmVmZWU2YTJiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzQ1N2Q0ZGI1YzNhMTRkMTI5MzI5NzMzZDFiNjdiODMwID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzcwZGYzNmI1MGM4NzQ4YTRiNDJmMDc0ZTEwZmM5OThkID0gJCgnPGRpdiBpZD0iaHRtbF83MGRmMzZiNTBjODc0OGE0YjQyZjA3NGUxMGZjOTk4ZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RGVlciBQYXJrLCBGb3Jlc3QgSGlsbCBTRSwgUmF0aG5lbGx5LCBTb3V0aCBIaWxsLCBTdW1tZXJoaWxsIFdlc3QgQ2x1c3RlciAwLjA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzQ1N2Q0ZGI1YzNhMTRkMTI5MzI5NzMzZDFiNjdiODMwLnNldENvbnRlbnQoaHRtbF83MGRmMzZiNTBjODc0OGE0YjQyZjA3NGUxMGZjOTk4ZCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8zYjM0Nzc0NDUwODg0YjY0YjMxMTk0ZWE5NmRlNDhjNi5iaW5kUG9wdXAocG9wdXBfNDU3ZDRkYjVjM2ExNGQxMjkzMjk3MzNkMWI2N2I4MzApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYjNlODgyNGYxMGE5NGViMjg5ZDk4YzFmODEzOTdhOWYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MTE2OTQ4LC03OS40MTY5MzU1OTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMzM4OGZmIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMzODhmZiIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kZjE2N2ZmMWYzNGE0ZDNhYjBlMjM2NWJlZmVlNmEyYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9lZjk0ZGIzYzM5ZjM0M2EwYjRhMDE1YjdmY2MzOTY1NyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF84NjljZjlmMWVmOTE0ZDY0YWViZTFmODJjYWExNTk2ZSA9ICQoJzxkaXYgaWQ9Imh0bWxfODY5Y2Y5ZjFlZjkxNGQ2NGFlYmUxZjgyY2FhMTU5NmUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlJvc2VsYXduIENsdXN0ZXIgMi4wPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9lZjk0ZGIzYzM5ZjM0M2EwYjRhMDE1YjdmY2MzOTY1Ny5zZXRDb250ZW50KGh0bWxfODY5Y2Y5ZjFlZjkxNGQ2NGFlYmUxZjgyY2FhMTU5NmUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYjNlODgyNGYxMGE5NGViMjg5ZDk4YzFmODEzOTdhOWYuYmluZFBvcHVwKHBvcHVwX2VmOTRkYjNjMzlmMzQzYTBiNGEwMTViN2ZjYzM5NjU3KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzY1YmQxNDdlNDE5NzQ1OWViMDVkZWRjNmQ2ZmRhMzJmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjk2OTQ3NiwtNzkuNDExMzA3MjAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzMzODhmZiIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMzg4ZmYiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZGYxNjdmZjFmMzRhNGQzYWIwZTIzNjViZWZlZTZhMmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYWYyZDRmZWRhODBkNGU0ZDg1Y2U5N2QxNDA0ZjNhYTYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMWNlMTVkMmU4ZDc3NDA0N2I3YjBjOTI3YmMxZTAwNmUgPSAkKCc8ZGl2IGlkPSJodG1sXzFjZTE1ZDJlOGQ3NzQwNDdiN2IwYzkyN2JjMWUwMDZlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Gb3Jlc3QgSGlsbCBOb3J0aCwgRm9yZXN0IEhpbGwgV2VzdCBDbHVzdGVyIDMuMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYWYyZDRmZWRhODBkNGU0ZDg1Y2U5N2QxNDA0ZjNhYTYuc2V0Q29udGVudChodG1sXzFjZTE1ZDJlOGQ3NzQwNDdiN2IwYzkyN2JjMWUwMDZlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzY1YmQxNDdlNDE5NzQ1OWViMDVkZWRjNmQ2ZmRhMzJmLmJpbmRQb3B1cChwb3B1cF9hZjJkNGZlZGE4MGQ0ZTRkODVjZTk3ZDE0MDRmM2FhNik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mNDQwODRmMWRmMjA0NDRhODUzNjE2YjZhZTY3M2JlZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY3MjcwOTcsLTc5LjQwNTY3ODQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMzMzg4ZmYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzM4OGZmIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2RmMTY3ZmYxZjM0YTRkM2FiMGUyMzY1YmVmZWU2YTJiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2FiNDE4ZDllZDhhNjRlNjBiYjA2ZWRhY2JjNThlY2U2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzc0NmIzMjk5NTA2ZjQ3MGJhZWIyYTgzNTQ5NGM0OGY4ID0gJCgnPGRpdiBpZD0iaHRtbF83NDZiMzI5OTUwNmY0NzBiYWViMmE4MzU0OTRjNDhmOCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VGhlIEFubmV4LCBOb3J0aCBNaWR0b3duLCBZb3JrdmlsbGUgQ2x1c3RlciAwLjA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2FiNDE4ZDllZDhhNjRlNjBiYjA2ZWRhY2JjNThlY2U2LnNldENvbnRlbnQoaHRtbF83NDZiMzI5OTUwNmY0NzBiYWViMmE4MzU0OTRjNDhmOCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mNDQwODRmMWRmMjA0NDRhODUzNjE2YjZhZTY3M2JlZi5iaW5kUG9wdXAocG9wdXBfYWI0MThkOWVkOGE2NGU2MGJiMDZlZGFjYmM1OGVjZTYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMTc5OTRkZDhjZjhkNGYwNzk0NjQ1YjFkYjJhNjgxNjUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42Nzk1NjI2LC03OS4zNzc1Mjk0MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMzM4OGZmIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMzODhmZiIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kZjE2N2ZmMWYzNGE0ZDNhYjBlMjM2NWJlZmVlNmEyYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mNjllZjdkOTc3M2E0NzQxYjJjODA0YTFhMmYwZGFkMSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF84ZmY5ZjIzNjgwYzI0OTZkOWM3NGViMzA3ZWViM2Q5NyA9ICQoJzxkaXYgaWQ9Imh0bWxfOGZmOWYyMzY4MGMyNDk2ZDljNzRlYjMwN2VlYjNkOTciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlJvc2VkYWxlIENsdXN0ZXIgMy4wPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mNjllZjdkOTc3M2E0NzQxYjJjODA0YTFhMmYwZGFkMS5zZXRDb250ZW50KGh0bWxfOGZmOWYyMzY4MGMyNDk2ZDljNzRlYjMwN2VlYjNkOTcpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMTc5OTRkZDhjZjhkNGYwNzk0NjQ1YjFkYjJhNjgxNjUuYmluZFBvcHVwKHBvcHVwX2Y2OWVmN2Q5NzczYTQ3NDFiMmM4MDRhMWEyZjBkYWQxKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2U0NDFmNzllMTAxNDQ1Y2VhOWVhZDA0YTM0MjI2NTVmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjY3OTY3LC03OS4zNjc2NzUzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMzMzg4ZmYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzM4OGZmIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2RmMTY3ZmYxZjM0YTRkM2FiMGUyMzY1YmVmZWU2YTJiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzIwYTU3MTcwYjc2YzRlYWY5ZjE0YzUyYzNkNTc1OWU3ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2RhYzRmNDVkMmNjYTRhZjdhMDMwNmUwM2VlYTU4ZGExID0gJCgnPGRpdiBpZD0iaHRtbF9kYWM0ZjQ1ZDJjY2E0YWY3YTAzMDZlMDNlZWE1OGRhMSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q2FiYmFnZXRvd24sIFN0LiBKYW1lcyBUb3duIENsdXN0ZXIgMC4wPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yMGE1NzE3MGI3NmM0ZWFmOWYxNGM1MmMzZDU3NTllNy5zZXRDb250ZW50KGh0bWxfZGFjNGY0NWQyY2NhNGFmN2EwMzA2ZTAzZWVhNThkYTEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZTQ0MWY3OWUxMDE0NDVjZWE5ZWFkMDRhMzQyMjY1NWYuYmluZFBvcHVwKHBvcHVwXzIwYTU3MTcwYjc2YzRlYWY5ZjE0YzUyYzNkNTc1OWU3KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzc0YjgxYmY4NjQ1ZTRlNjI4OGVlZGRiNDhkYmM4NzkzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjY1ODU5OSwtNzkuMzgzMTU5OTAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzMzODhmZiIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMzg4ZmYiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZGYxNjdmZjFmMzRhNGQzYWIwZTIzNjViZWZlZTZhMmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMzg5ODhlYTUyOTBiNDJmMjkyOTZhNDAwODIxNDc2YmYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYjQzZjk4OTNkMTVjNDkyM2FmZThhNzM3YjRlZjdjYmMgPSAkKCc8ZGl2IGlkPSJodG1sX2I0M2Y5ODkzZDE1YzQ5MjNhZmU4YTczN2I0ZWY3Y2JjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DaHVyY2ggYW5kIFdlbGxlc2xleSBDbHVzdGVyIDAuMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMzg5ODhlYTUyOTBiNDJmMjkyOTZhNDAwODIxNDc2YmYuc2V0Q29udGVudChodG1sX2I0M2Y5ODkzZDE1YzQ5MjNhZmU4YTczN2I0ZWY3Y2JjKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzc0YjgxYmY4NjQ1ZTRlNjI4OGVlZGRiNDhkYmM4NzkzLmJpbmRQb3B1cChwb3B1cF8zODk4OGVhNTI5MGI0MmYyOTI5NmE0MDA4MjE0NzZiZik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mYmE1MDIwNDJhZWU0MDA3OGVmYzFmYWU5YjJjYTIzYiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY1NDI1OTksLTc5LjM2MDYzNTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzMzODhmZiIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMzg4ZmYiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZGYxNjdmZjFmMzRhNGQzYWIwZTIzNjViZWZlZTZhMmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZGU0MmM0ZjYzOWM2NDBkMTg5NDRlZjE5ZWQ2YTEwNzcgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNTNlZDAzZTQ0YjJhNDM2MGJjMDFmNzRhOTNhNTBjZDIgPSAkKCc8ZGl2IGlkPSJodG1sXzUzZWQwM2U0NGIyYTQzNjBiYzAxZjc0YTkzYTUwY2QyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IYXJib3VyZnJvbnQgQ2x1c3RlciAwLjA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2RlNDJjNGY2MzljNjQwZDE4OTQ0ZWYxOWVkNmExMDc3LnNldENvbnRlbnQoaHRtbF81M2VkMDNlNDRiMmE0MzYwYmMwMWY3NGE5M2E1MGNkMik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mYmE1MDIwNDJhZWU0MDA3OGVmYzFmYWU5YjJjYTIzYi5iaW5kUG9wdXAocG9wdXBfZGU0MmM0ZjYzOWM2NDBkMTg5NDRlZjE5ZWQ2YTEwNzcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYjI3ZTI0MGJiYTMyNDEwMWFkN2M5NGYyODIyOGI3YzEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NTcxNjE4LC03OS4zNzg5MzcwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMzM4OGZmIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMzODhmZiIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kZjE2N2ZmMWYzNGE0ZDNhYjBlMjM2NWJlZmVlNmEyYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xMzlkYzM4ODIxYjg0MDFmOWMyMjc3NzM4Yzg1NzhkYyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9hYzkyMDRjMWVmNWU0MDMxOTZmNjdhZGMxMWQwMGJjNCA9ICQoJzxkaXYgaWQ9Imh0bWxfYWM5MjA0YzFlZjVlNDAzMTk2ZjY3YWRjMTFkMDBiYzQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlJ5ZXJzb24sIEdhcmRlbiBEaXN0cmljdCBDbHVzdGVyIDAuMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMTM5ZGMzODgyMWI4NDAxZjljMjI3NzczOGM4NTc4ZGMuc2V0Q29udGVudChodG1sX2FjOTIwNGMxZWY1ZTQwMzE5NmY2N2FkYzExZDAwYmM0KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2IyN2UyNDBiYmEzMjQxMDFhZDdjOTRmMjgyMjhiN2MxLmJpbmRQb3B1cChwb3B1cF8xMzlkYzM4ODIxYjg0MDFmOWMyMjc3NzM4Yzg1NzhkYyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hOWY1MWI5ZTIzOWU0YTY5YTcwZWRjYTU3ZWVjODUxZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY1MTQ5MzksLTc5LjM3NTQxNzldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzMzODhmZiIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMzg4ZmYiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZGYxNjdmZjFmMzRhNGQzYWIwZTIzNjViZWZlZTZhMmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYzljYTNjN2Y1ZGQ3NDUzYzk2NTVmOTliODk1ODY1MTQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYjBmZDg2NDViYTE1NDY2Yzg4NDIyM2M3N2NhZDZkNzYgPSAkKCc8ZGl2IGlkPSJodG1sX2IwZmQ4NjQ1YmExNTQ2NmM4ODQyMjNjNzdjYWQ2ZDc2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TdC4gSmFtZXMgVG93biBDbHVzdGVyIDAuMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYzljYTNjN2Y1ZGQ3NDUzYzk2NTVmOTliODk1ODY1MTQuc2V0Q29udGVudChodG1sX2IwZmQ4NjQ1YmExNTQ2NmM4ODQyMjNjNzdjYWQ2ZDc2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2E5ZjUxYjllMjM5ZTRhNjlhNzBlZGNhNTdlZWM4NTFkLmJpbmRQb3B1cChwb3B1cF9jOWNhM2M3ZjVkZDc0NTNjOTY1NWY5OWI4OTU4NjUxNCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83NWViYTQyNzE4ZTI0OTA5OTVmMWRlOTUzYjRhZDUwNyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY0NDc3MDc5OTk5OTk5NiwtNzkuMzczMzA2NF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMzM4OGZmIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMzODhmZiIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kZjE2N2ZmMWYzNGE0ZDNhYjBlMjM2NWJlZmVlNmEyYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mMjdjZTFmMzBjZjU0NTI4ODQ0NzdhZDdjNmI3YmE3OSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lZWIyN2E0NDk3OTk0MjFjOGFlY2ZmMGFkNjE4NzlmNiA9ICQoJzxkaXYgaWQ9Imh0bWxfZWViMjdhNDQ5Nzk5NDIxYzhhZWNmZjBhZDYxODc5ZjYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJlcmN6eSBQYXJrIENsdXN0ZXIgMC4wPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mMjdjZTFmMzBjZjU0NTI4ODQ0NzdhZDdjNmI3YmE3OS5zZXRDb250ZW50KGh0bWxfZWViMjdhNDQ5Nzk5NDIxYzhhZWNmZjBhZDYxODc5ZjYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNzVlYmE0MjcxOGUyNDkwOTk1ZjFkZTk1M2I0YWQ1MDcuYmluZFBvcHVwKHBvcHVwX2YyN2NlMWYzMGNmNTQ1Mjg4NDQ3N2FkN2M2YjdiYTc5KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2UzZGI3NTVkOWJmNDRjMDRiODNiODlkZjI2MzUwYmRlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjU3OTUyNCwtNzkuMzg3MzgyNl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMzM4OGZmIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMzODhmZiIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kZjE2N2ZmMWYzNGE0ZDNhYjBlMjM2NWJlZmVlNmEyYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yMTY4ZGQ4YmQ0MDI0ODllODFhZDM1ODJhMDUxNTc2MiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8zZTYyMDY2NjkxMjk0OTgzOTY5M2Y3N2JjOGE0NWVhZiA9ICQoJzxkaXYgaWQ9Imh0bWxfM2U2MjA2NjY5MTI5NDk4Mzk2OTNmNzdiYzhhNDVlYWYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNlbnRyYWwgQmF5IFN0cmVldCBDbHVzdGVyIDAuMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMjE2OGRkOGJkNDAyNDg5ZTgxYWQzNTgyYTA1MTU3NjIuc2V0Q29udGVudChodG1sXzNlNjIwNjY2OTEyOTQ5ODM5NjkzZjc3YmM4YTQ1ZWFmKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2UzZGI3NTVkOWJmNDRjMDRiODNiODlkZjI2MzUwYmRlLmJpbmRQb3B1cChwb3B1cF8yMTY4ZGQ4YmQ0MDI0ODllODFhZDM1ODJhMDUxNTc2Mik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xYjY3NjJmYmI0MTQ0ZjE4ODk3ZjFiNGMwNGFmZDk5MSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY1MDU3MTIwMDAwMDAxLC03OS4zODQ1Njc1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMzMzg4ZmYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzM4OGZmIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2RmMTY3ZmYxZjM0YTRkM2FiMGUyMzY1YmVmZWU2YTJiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2MyMTdhZWI3YTI0YTRlNjQ5MmExMDQ5NzYwY2Y4ZmZjID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzViYzY4NzAwYmM4NDRlZTJhZGY5MzFmYmRjZTRhMTY0ID0gJCgnPGRpdiBpZD0iaHRtbF81YmM2ODcwMGJjODQ0ZWUyYWRmOTMxZmJkY2U0YTE2NCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QWRlbGFpZGUsIEtpbmcsIFJpY2htb25kIENsdXN0ZXIgMC4wPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jMjE3YWViN2EyNGE0ZTY0OTJhMTA0OTc2MGNmOGZmYy5zZXRDb250ZW50KGh0bWxfNWJjNjg3MDBiYzg0NGVlMmFkZjkzMWZiZGNlNGExNjQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMWI2NzYyZmJiNDE0NGYxODg5N2YxYjRjMDRhZmQ5OTEuYmluZFBvcHVwKHBvcHVwX2MyMTdhZWI3YTI0YTRlNjQ5MmExMDQ5NzYwY2Y4ZmZjKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzFlYWQ1NjllZjQwNDRmYjc5MGMyZTZhZWIyYzhhOWIyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjQwODE1NywtNzkuMzgxNzUyMjk5OTk5OTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzMzODhmZiIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMzg4ZmYiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZGYxNjdmZjFmMzRhNGQzYWIwZTIzNjViZWZlZTZhMmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMWVjNjcwZjAxZDA2NDgxZjg5Njk4MWY2Yzk2ODZjOWMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYTVhNTEwNmE4NTk4NGE2YmFmNWY5MGE0MDk4MjQ2YzQgPSAkKCc8ZGl2IGlkPSJodG1sX2E1YTUxMDZhODU5ODRhNmJhZjVmOTBhNDA5ODI0NmM0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IYXJib3VyZnJvbnQgRWFzdCwgVG9yb250byBJc2xhbmRzLCBVbmlvbiBTdGF0aW9uIENsdXN0ZXIgMC4wPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8xZWM2NzBmMDFkMDY0ODFmODk2OTgxZjZjOTY4NmM5Yy5zZXRDb250ZW50KGh0bWxfYTVhNTEwNmE4NTk4NGE2YmFmNWY5MGE0MDk4MjQ2YzQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMWVhZDU2OWVmNDA0NGZiNzkwYzJlNmFlYjJjOGE5YjIuYmluZFBvcHVwKHBvcHVwXzFlYzY3MGYwMWQwNjQ4MWY4OTY5ODFmNmM5Njg2YzljKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzdjZjI0ZDlkZTdiMTQyNWQ5OTM1NzYxYWZkNzg2ODU4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjQ3MTc2OCwtNzkuMzgxNTc2NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzMzODhmZiIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMzg4ZmYiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZGYxNjdmZjFmMzRhNGQzYWIwZTIzNjViZWZlZTZhMmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNjRkOGNmNjc4M2FhNGY2ODlkNzA0MWYwMGVkMjkxMDEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNjRlZGUxODhlNmQ4NDk0MGE1ZmUxMGI1Mjg4OTY5ZDYgPSAkKCc8ZGl2IGlkPSJodG1sXzY0ZWRlMTg4ZTZkODQ5NDBhNWZlMTBiNTI4ODk2OWQ2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5EZXNpZ24gRXhjaGFuZ2UsIFRvcm9udG8gRG9taW5pb24gQ2VudHJlIENsdXN0ZXIgMC4wPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82NGQ4Y2Y2NzgzYWE0ZjY4OWQ3MDQxZjAwZWQyOTEwMS5zZXRDb250ZW50KGh0bWxfNjRlZGUxODhlNmQ4NDk0MGE1ZmUxMGI1Mjg4OTY5ZDYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfN2NmMjRkOWRlN2IxNDI1ZDk5MzU3NjFhZmQ3ODY4NTguYmluZFBvcHVwKHBvcHVwXzY0ZDhjZjY3ODNhYTRmNjg5ZDcwNDFmMDBlZDI5MTAxKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzUwN2UxNzRjNzU4ZTQ1N2NhNThlOGU1Y2M5NmQyY2FkID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjQ4MTk4NSwtNzkuMzc5ODE2OTAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzMzODhmZiIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMzg4ZmYiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZGYxNjdmZjFmMzRhNGQzYWIwZTIzNjViZWZlZTZhMmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYmJiNzNjOGQzMjNlNGZhMTkxZGQzMzk2OWVhNzNhYTIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYjQ4ZjVkMjdhMjVmNGEwOTlhMWExYzY4NDFiMjRlMDMgPSAkKCc8ZGl2IGlkPSJodG1sX2I0OGY1ZDI3YTI1ZjRhMDk5YTFhMWM2ODQxYjI0ZTAzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Db21tZXJjZSBDb3VydCwgVmljdG9yaWEgSG90ZWwgQ2x1c3RlciAwLjA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2JiYjczYzhkMzIzZTRmYTE5MWRkMzM5NjllYTczYWEyLnNldENvbnRlbnQoaHRtbF9iNDhmNWQyN2EyNWY0YTA5OWExYTFjNjg0MWIyNGUwMyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl81MDdlMTc0Yzc1OGU0NTdjYTU4ZThlNWNjOTZkMmNhZC5iaW5kUG9wdXAocG9wdXBfYmJiNzNjOGQzMjNlNGZhMTkxZGQzMzk2OWVhNzNhYTIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYjYxZjUyZTc2YzcwNDRjYTgwYzg4ZDQ2NzRjOTMwMzkgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NjI2OTU2LC03OS40MDAwNDkzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMzMzg4ZmYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzM4OGZmIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2RmMTY3ZmYxZjM0YTRkM2FiMGUyMzY1YmVmZWU2YTJiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzA5NzE5OTRlZjE4NjQwMmQ4NDEwMjE2OTg2NWM0NjI5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzZiZmIyZjA5YmQ2MTQzY2Y4NjE0N2QzNTVkZTI5MzYyID0gJCgnPGRpdiBpZD0iaHRtbF82YmZiMmYwOWJkNjE0M2NmODYxNDdkMzU1ZGUyOTM2MiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SGFyYm9yZCwgVW5pdmVyc2l0eSBvZiBUb3JvbnRvIENsdXN0ZXIgMC4wPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8wOTcxOTk0ZWYxODY0MDJkODQxMDIxNjk4NjVjNDYyOS5zZXRDb250ZW50KGh0bWxfNmJmYjJmMDliZDYxNDNjZjg2MTQ3ZDM1NWRlMjkzNjIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYjYxZjUyZTc2YzcwNDRjYTgwYzg4ZDQ2NzRjOTMwMzkuYmluZFBvcHVwKHBvcHVwXzA5NzE5OTRlZjE4NjQwMmQ4NDEwMjE2OTg2NWM0NjI5KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzc0OTc2NDRlMzk3NTRjOWViNGI4MTFmMWMxYjNjNzJkID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjUzMjA1NywtNzkuNDAwMDQ5M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMzM4OGZmIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMzODhmZiIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kZjE2N2ZmMWYzNGE0ZDNhYjBlMjM2NWJlZmVlNmEyYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82Nzk3NzY1NTkwZDg0NWI4OTdiZTg4YWU3Y2U3NGM5ZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF85ZWRhNmM0M2Y3NTU0YmZjYTgwMmM5MjlkYjFhYzE1OCA9ICQoJzxkaXYgaWQ9Imh0bWxfOWVkYTZjNDNmNzU1NGJmY2E4MDJjOTI5ZGIxYWMxNTgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNoaW5hdG93biwgR3JhbmdlIFBhcmssIEtlbnNpbmd0b24gTWFya2V0IENsdXN0ZXIgMC4wPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82Nzk3NzY1NTkwZDg0NWI4OTdiZTg4YWU3Y2U3NGM5ZS5zZXRDb250ZW50KGh0bWxfOWVkYTZjNDNmNzU1NGJmY2E4MDJjOTI5ZGIxYWMxNTgpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNzQ5NzY0NGUzOTc1NGM5ZWI0YjgxMWYxYzFiM2M3MmQuYmluZFBvcHVwKHBvcHVwXzY3OTc3NjU1OTBkODQ1Yjg5N2JlODhhZTdjZTc0YzllKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2E4MWQ5YjJmMDhkNDQ1ZTc4NTM3ZDc1MWUyOTBlZTFjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjI4OTQ2NywtNzkuMzk0NDE5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMzM4OGZmIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMzODhmZiIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kZjE2N2ZmMWYzNGE0ZDNhYjBlMjM2NWJlZmVlNmEyYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iOTQzZjZmYTg4Nzg0NzVmODZjNjBmNmRjMzE5NzdmYSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lYjIyMjI4MTAwNDE0M2FhYWQ1YmQ5NDYyNDUyNjBkNiA9ICQoJzxkaXYgaWQ9Imh0bWxfZWIyMjIyODEwMDQxNDNhYWFkNWJkOTQ2MjQ1MjYwZDYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNOIFRvd2VyLCBCYXRodXJzdCBRdWF5LCBJc2xhbmQgYWlycG9ydCwgSGFyYm91cmZyb250IFdlc3QsIEtpbmcgYW5kIFNwYWRpbmEsIFJhaWx3YXkgTGFuZHMsIFNvdXRoIE5pYWdhcmEgQ2x1c3RlciAwLjA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2I5NDNmNmZhODg3ODQ3NWY4NmM2MGY2ZGMzMTk3N2ZhLnNldENvbnRlbnQoaHRtbF9lYjIyMjI4MTAwNDE0M2FhYWQ1YmQ5NDYyNDUyNjBkNik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9hODFkOWIyZjA4ZDQ0NWU3ODUzN2Q3NTFlMjkwZWUxYy5iaW5kUG9wdXAocG9wdXBfYjk0M2Y2ZmE4ODc4NDc1Zjg2YzYwZjZkYzMxOTc3ZmEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMTdiNWQ0OGZlOGVkNGQzY2JhOTFmYjZmZTlhYzlmNDIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDY0MzUyLC03OS4zNzQ4NDU5OTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMzM4OGZmIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMzODhmZiIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kZjE2N2ZmMWYzNGE0ZDNhYjBlMjM2NWJlZmVlNmEyYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wZTQ3NWE5MWJjMTY0MjhhOGQ1Mjg2ZTI2ZGRmNDIzZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mZWFhNmQ4MTBmNGU0Mzc2OTJhMTE1NTI2MzEwNzQ3YiA9ICQoJzxkaXYgaWQ9Imh0bWxfZmVhYTZkODEwZjRlNDM3NjkyYTExNTUyNjMxMDc0N2IiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlN0biBBIFBPIEJveGVzIDI1IFRoZSBFc3BsYW5hZGUgQ2x1c3RlciAwLjA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzBlNDc1YTkxYmMxNjQyOGE4ZDUyODZlMjZkZGY0MjNlLnNldENvbnRlbnQoaHRtbF9mZWFhNmQ4MTBmNGU0Mzc2OTJhMTE1NTI2MzEwNzQ3Yik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8xN2I1ZDQ4ZmU4ZWQ0ZDNjYmE5MWZiNmZlOWFjOWY0Mi5iaW5kUG9wdXAocG9wdXBfMGU0NzVhOTFiYzE2NDI4YThkNTI4NmUyNmRkZjQyM2UpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMDVjNDRkM2FhNTZkNDY1ZGJjNGMzNzRkYjRjNDAzNWYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDg0MjkyLC03OS4zODIyODAyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMzMzg4ZmYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzM4OGZmIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2RmMTY3ZmYxZjM0YTRkM2FiMGUyMzY1YmVmZWU2YTJiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2JhN2YyODkxMGJlMzQ1NTJiZGEzNzk2ZThiZjU3NzljID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2UwYzVlMjY3YzQ5NTRjZDc4ZGJhNjIxZTBhMDhjNmE2ID0gJCgnPGRpdiBpZD0iaHRtbF9lMGM1ZTI2N2M0OTU0Y2Q3OGRiYTYyMWUwYTA4YzZhNiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Rmlyc3QgQ2FuYWRpYW4gUGxhY2UsIFVuZGVyZ3JvdW5kIGNpdHkgQ2x1c3RlciAwLjA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2JhN2YyODkxMGJlMzQ1NTJiZGEzNzk2ZThiZjU3NzljLnNldENvbnRlbnQoaHRtbF9lMGM1ZTI2N2M0OTU0Y2Q3OGRiYTYyMWUwYTA4YzZhNik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wNWM0NGQzYWE1NmQ0NjVkYmM0YzM3NGRiNGM0MDM1Zi5iaW5kUG9wdXAocG9wdXBfYmE3ZjI4OTEwYmUzNDU1MmJkYTM3OTZlOGJmNTc3OWMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfM2I1MzI3OTZlMTQ4NGI2ZTk1NTVkNDE2MjgxNDc2NzggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42Njk1NDIsLTc5LjQyMjU2MzddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzMzODhmZiIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMzg4ZmYiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZGYxNjdmZjFmMzRhNGQzYWIwZTIzNjViZWZlZTZhMmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMGU2NGU3MjMxZWJjNDEzNGFlODEyN2YwNGMwZTJjNzcgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZmJhYWVhZjU1YmNlNGE3NTkwMDljZDczODBkNzEwNTYgPSAkKCc8ZGl2IGlkPSJodG1sX2ZiYWFlYWY1NWJjZTRhNzU5MDA5Y2Q3MzgwZDcxMDU2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DaHJpc3RpZSBDbHVzdGVyIDAuMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMGU2NGU3MjMxZWJjNDEzNGFlODEyN2YwNGMwZTJjNzcuc2V0Q29udGVudChodG1sX2ZiYWFlYWY1NWJjZTRhNzU5MDA5Y2Q3MzgwZDcxMDU2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzNiNTMyNzk2ZTE0ODRiNmU5NTU1ZDQxNjI4MTQ3Njc4LmJpbmRQb3B1cChwb3B1cF8wZTY0ZTcyMzFlYmM0MTM0YWU4MTI3ZjA0YzBlMmM3Nyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xYTFmYjc1OTcxMDU0NzcwODk2OTI0Zjk4MjQwYmZiMSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY2Nzg1NTYsLTc5LjUzMjI0MjQwMDAwMDAyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMzMzg4ZmYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzM4OGZmIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2RmMTY3ZmYxZjM0YTRkM2FiMGUyMzY1YmVmZWU2YTJiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzI3MDRmYTVhMzJjOTRlOTBhMmViNjdlODlkNTI4NWE1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzk4MzEzZTZjYmY0YTQyZTJiNzYwN2E4MGYzZTQ3Mzg3ID0gJCgnPGRpdiBpZD0iaHRtbF85ODMxM2U2Y2JmNGE0MmUyYjc2MDdhODBmM2U0NzM4NyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UXVlZW4mIzM5O3MgUGFyayBDbHVzdGVyIG5hbjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMjcwNGZhNWEzMmM5NGU5MGEyZWI2N2U4OWQ1Mjg1YTUuc2V0Q29udGVudChodG1sXzk4MzEzZTZjYmY0YTQyZTJiNzYwN2E4MGYzZTQ3Mzg3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzFhMWZiNzU5NzEwNTQ3NzA4OTY5MjRmOTgyNDBiZmIxLmJpbmRQb3B1cChwb3B1cF8yNzA0ZmE1YTMyYzk0ZTkwYTJlYjY3ZTg5ZDUyODVhNSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hZWM4MmY1NmQ5ZWQ0YmE5OTQ2NDAwNDgxYzUzNDJmZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY2OTAwNTEwMDAwMDAxLC03OS40NDIyNTkzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMzMzg4ZmYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzM4OGZmIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2RmMTY3ZmYxZjM0YTRkM2FiMGUyMzY1YmVmZWU2YTJiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzUwNDdlNDE2YjRhMjQ2YjhhNWIzMzYzMzI2NGQ2ZWFiID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzZkYWE1NTIxN2FlNDQyNTJhOTJhYzI4NzZlZjk4N2U4ID0gJCgnPGRpdiBpZD0iaHRtbF82ZGFhNTUyMTdhZTQ0MjUyYTkyYWMyODc2ZWY5ODdlOCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RG92ZXJjb3VydCBWaWxsYWdlLCBEdWZmZXJpbiBDbHVzdGVyIDAuMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNTA0N2U0MTZiNGEyNDZiOGE1YjMzNjMzMjY0ZDZlYWIuc2V0Q29udGVudChodG1sXzZkYWE1NTIxN2FlNDQyNTJhOTJhYzI4NzZlZjk4N2U4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2FlYzgyZjU2ZDllZDRiYTk5NDY0MDA0ODFjNTM0MmZmLmJpbmRQb3B1cChwb3B1cF81MDQ3ZTQxNmI0YTI0NmI4YTViMzM2MzMyNjRkNmVhYik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80NWMwNjJlMThiZDk0ZjUxODk1NTYzYWZkY2QzYjM5MSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY0NzkyNjcwMDAwMDAwNiwtNzkuNDE5NzQ5N10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMzM4OGZmIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMzODhmZiIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kZjE2N2ZmMWYzNGE0ZDNhYjBlMjM2NWJlZmVlNmEyYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yMzdiY2M5OGIwMmE0YTdjYWE2ZDFkMTc3MjBkOGVkYiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jZjc2NzQzMTkyYWM0ZjgyYTg5YWU3YTI4NTllZWQ4ZCA9ICQoJzxkaXYgaWQ9Imh0bWxfY2Y3Njc0MzE5MmFjNGY4MmE4OWFlN2EyODU5ZWVkOGQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkxpdHRsZSBQb3J0dWdhbCwgVHJpbml0eSBDbHVzdGVyIDAuMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMjM3YmNjOThiMDJhNGE3Y2FhNmQxZDE3NzIwZDhlZGIuc2V0Q29udGVudChodG1sX2NmNzY3NDMxOTJhYzRmODJhODlhZTdhMjg1OWVlZDhkKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzQ1YzA2MmUxOGJkOTRmNTE4OTU1NjNhZmRjZDNiMzkxLmJpbmRQb3B1cChwb3B1cF8yMzdiY2M5OGIwMmE0YTdjYWE2ZDFkMTc3MjBkOGVkYik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl85Njk3MzkxM2YxMTI0OTJlYTJlNGJiNzIyNjVkNTVhOSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjYzNjg0NzIsLTc5LjQyODE5MTQwMDAwMDAyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMzMzg4ZmYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzM4OGZmIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2RmMTY3ZmYxZjM0YTRkM2FiMGUyMzY1YmVmZWU2YTJiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2Q3ZmM2ZDhjOTc3YzRmMDg5NDQ4N2U5OTNkYTlmMDAyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzAzMWVlMWE1N2U3MjQyNzRhZDg2MWU1OGJhMjJiNDIzID0gJCgnPGRpdiBpZD0iaHRtbF8wMzFlZTFhNTdlNzI0Mjc0YWQ4NjFlNThiYTIyYjQyMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QnJvY2t0b24sIEV4aGliaXRpb24gUGxhY2UsIFBhcmtkYWxlIFZpbGxhZ2UgQ2x1c3RlciAwLjA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2Q3ZmM2ZDhjOTc3YzRmMDg5NDQ4N2U5OTNkYTlmMDAyLnNldENvbnRlbnQoaHRtbF8wMzFlZTFhNTdlNzI0Mjc0YWQ4NjFlNThiYTIyYjQyMyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85Njk3MzkxM2YxMTI0OTJlYTJlNGJiNzIyNjVkNTVhOS5iaW5kUG9wdXAocG9wdXBfZDdmYzZkOGM5NzdjNGYwODk0NDg3ZTk5M2RhOWYwMDIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMDRhZjk5ZmUyZmYyNDRiYmJkNWVhMjViMmUyZTVmZjAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NjE2MDgzLC03OS40NjQ3NjMyOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMzM4OGZmIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMzODhmZiIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kZjE2N2ZmMWYzNGE0ZDNhYjBlMjM2NWJlZmVlNmEyYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81MWQ5NWQ1MjkxZjU0YTliOGNiODYxYzA4OTE0NzhmMyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lNjE2ZGRjMDQ2Y2M0YWFlOGYxNWNlMzBhMDNiOWI3NCA9ICQoJzxkaXYgaWQ9Imh0bWxfZTYxNmRkYzA0NmNjNGFhZThmMTVjZTMwYTAzYjliNzQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhpZ2ggUGFyaywgVGhlIEp1bmN0aW9uIFNvdXRoIENsdXN0ZXIgMC4wPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81MWQ5NWQ1MjkxZjU0YTliOGNiODYxYzA4OTE0NzhmMy5zZXRDb250ZW50KGh0bWxfZTYxNmRkYzA0NmNjNGFhZThmMTVjZTMwYTAzYjliNzQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMDRhZjk5ZmUyZmYyNDRiYmJkNWVhMjViMmUyZTVmZjAuYmluZFBvcHVwKHBvcHVwXzUxZDk1ZDUyOTFmNTRhOWI4Y2I4NjFjMDg5MTQ3OGYzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzBlZmRhODdkYzExZjRiNzM5NWY0NzVlNDcyMjY5MzJiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjQ4OTU5NywtNzkuNDU2MzI1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMzMzg4ZmYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzM4OGZmIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2RmMTY3ZmYxZjM0YTRkM2FiMGUyMzY1YmVmZWU2YTJiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzkwYjM5MDUyOThhODRhNjJiNDgwY2VlNWJjMzIxMDg2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzkxYTVmNTA0ZmZkMTRmY2ZiMTQ5ODE5ZmMwOGFjY2IzID0gJCgnPGRpdiBpZD0iaHRtbF85MWE1ZjUwNGZmZDE0ZmNmYjE0OTgxOWZjMDhhY2NiMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UGFya2RhbGUsIFJvbmNlc3ZhbGxlcyBDbHVzdGVyIDAuMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOTBiMzkwNTI5OGE4NGE2MmI0ODBjZWU1YmMzMjEwODYuc2V0Q29udGVudChodG1sXzkxYTVmNTA0ZmZkMTRmY2ZiMTQ5ODE5ZmMwOGFjY2IzKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzBlZmRhODdkYzExZjRiNzM5NWY0NzVlNDcyMjY5MzJiLmJpbmRQb3B1cChwb3B1cF85MGIzOTA1Mjk4YTg0YTYyYjQ4MGNlZTViYzMyMTA4Nik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8zYjg3Mzc3ODQxYzc0YWVlYTE0YjZlM2FhYzk2NDM5YiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY1MTU3MDYsLTc5LjQ4NDQ0OTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzMzODhmZiIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMzg4ZmYiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZGYxNjdmZjFmMzRhNGQzYWIwZTIzNjViZWZlZTZhMmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYTcyNjMxYzMyMjM0NDViNjlkYzE2YzlkYjM0NTE2MzkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOTM5MmU4M2YxMGE3NDMxZDlmMjQ1ZTIzYzA3ZWY0MTAgPSAkKCc8ZGl2IGlkPSJodG1sXzkzOTJlODNmMTBhNzQzMWQ5ZjI0NWUyM2MwN2VmNDEwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5SdW5ueW1lZGUsIFN3YW5zZWEgQ2x1c3RlciAwLjA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2E3MjYzMWMzMjIzNDQ1YjY5ZGMxNmM5ZGIzNDUxNjM5LnNldENvbnRlbnQoaHRtbF85MzkyZTgzZjEwYTc0MzFkOWYyNDVlMjNjMDdlZjQxMCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8zYjg3Mzc3ODQxYzc0YWVlYTE0YjZlM2FhYzk2NDM5Yi5iaW5kUG9wdXAocG9wdXBfYTcyNjMxYzMyMjM0NDViNjlkYzE2YzlkYjM0NTE2MzkpOwoKICAgICAgICAgICAgCiAgICAgICAgCjwvc2NyaXB0Pg==\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
      ],
      "text/plain": [
       "<folium.folium.Map at 0x1a1c92c0b8>"
      ]
     },
     "execution_count": 86,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# visualize clusters\n",
    "# create map\n",
    "map_clusters = folium.Map(location=[latitude, longitude], zoom_start=11)\n",
    "\n",
    "# set color scheme for the clusters\n",
    "x = np.arange(kclusters)\n",
    "ys = [i + x + (i*x)**2 for i in range(kclusters)]\n",
    "colors_array = cm.rainbow(np.linspace(0, 1, len(ys)))\n",
    "rainbow = [colors.rgb2hex(i) for i in colors_array]\n",
    "\n",
    "# add markers to the map\n",
    "markers_colors = []\n",
    "for lat, lon, poi, cluster in zip(toronto_merged['Latitude'], toronto_merged['Longitude'], toronto_merged['Neighborhood'], toronto_merged['Cluster Labels']):\n",
    "    label = folium.Popup(str(poi) + ' Cluster ' + str(cluster), parse_html=True)\n",
    "    folium.CircleMarker(\n",
    "        [lat, lon],\n",
    "        radius=5,\n",
    "        popup=label,\n",
    "        #color=rainbow[cluster-1],\n",
    "        fill=True,\n",
    "        #fill_color=rainbow[cluster-1],\n",
    "        fill_opacity=0.7).add_to(map_clusters)\n",
    "       \n",
    "map_clusters"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
